Java基础
泛型
用泛型写个快排
public class QuickSort01 {public static void main(String[] args) {// Integer array[] = {2,1,4,5,0};String array[] = {"2","1","4","5","0"};// ListNode listNode = new ListNode(2);// ListNode[] array = {listNode};quickSort(array);for (int i = 0; i < array.length; i++) {System.out.println(array[i]);}}//你只能传一个实现了Comparable接口的类型,比如Integer/String/Long...public static <T extends Comparable> void quickSort(T [] array){quickSort(array,0,array.length-1);}private static <T extends Comparable> void quickSort(T[] array, int start, int end) {int index = getIndex(array, start, end);if(index>start){quickSort(array,start,index-1);}if(index<end){quickSort(array,index+1,end);}}public static <T extends Comparable> int getIndex(T[] array,int start,int end){T pivot = array[start];while(start<end){while (start<end&&array[end].compareTo(pivot)>=0){end--;}array[start] = array[end];while (start<end&&array[start].compareTo(pivot)<=0){start++;}array[end] = array[start];}array[start] = pivot;return start;}}
注解
@Retention作用是定义被它所注解的注解保留多久,一共有三种策略,定义在RetentionPolicy枚举中.
从注释上看:
source:注解只保留在源文件,当Java文件编译成class文件的时候,注解被遗弃;被编译器忽略
class:注解被保留到class文件,但jvm加载class文件时候被遗弃,这是默认的生命周期
runtime:注解不仅被保存到class文件中,jvm加载class文件之后,仍然存在
强制类型转换
java中引用类型的强制转换:自下而上转型是顺其自然的,因为父类的功能本来就少,所以无需强制转换,比如Fruit apple = new Apple()就是一种向上转换;但自上而下转换是需要强制转换的,强制转换能否成功,要看被强制转换的那个对象本质上是个什么对象(由生成它的构造器决定)。
@Testpublic void test01(){Fruit fruit = hello();Apple apple = (Apple) fruit;System.out.println(apple);}public Fruit hello(){//这种不会报错,因为使用的构造器决定了返回值本质上是一个Apple// Apple apple = new Apple();// apple.name = "apple";// apple.apple = true;//这种会报错,因为使用的构造器决定了返回值本质上是一个FruitFruit apple = new Fruit();apple.name="apple";return apple;}
反射实战
实现一个简易的@Controller和@RequestMapping
<?xml version="1.0" encoding="UTF-8"?><web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"version="4.0"><servlet><servlet-name>MyServlet</servlet-name><servlet-class>com.example.servlettest.MyServlet</servlet-class><init-param><description>配置要扫描包及其子包, 如果有多个包,以逗号分隔</description><param-name>controllerPackage</param-name><param-value>com.example.servlettest.controller</param-value><!-- <param-value>me.gacl.web.controller</param-value> --></init-param><load-on-startup>1</load-on-startup></servlet><servlet-mapping><servlet-name>MyServlet</servlet-name><!-- 拦截所有以.do后缀结尾的请求 --><url-pattern>*.xjf</url-pattern></servlet-mapping></web-app>
public class MyServlet extends HttpServlet {
public static Map<String, Class<?>> map = new HashMap<>();
@Override
public void init(ServletConfig config) throws ServletException {
super.init(config);
String controllerPackage = config.getInitParameter("controllerPackage");
Set<Class<?>> classes = getClasses(controllerPackage);//拿到所有的controller
for (Class<?> clazz : classes) {
if (clazz.isAnnotationPresent(Controller.class)) {
Method[] methods = clazz.getDeclaredMethods();
for (Method method : methods) {
if (method.isAnnotationPresent(RequestMapping.class)) {
map.put(method.getAnnotation(RequestMapping.class).value(), clazz);
}
}
}
}
}
private Set<Class<?>> getClasses(String controllerPackage) {
Set<Class<?>> classes = new HashSet<>();
String classAbsUrl = "";
try {
//得到类路径(放.class的地方)
classAbsUrl = Thread.currentThread().getContextClassLoader().getResources("").nextElement().getFile();
} catch (IOException e) {
e.printStackTrace();
}
//根据包名,找到.class文件所在的具体文件夹(加上包名就可以了)
File file = new File(classAbsUrl + controllerPackage.replace('.', '/') + '/');
File[] files = file.listFiles();//File类很强大呀,给他个路径它就能列出所有文件
for (File f : files) {
String s = f.getName();//MyController.class,后面要去掉.class后缀
try {
Class<?> clazz = Thread.currentThread().getContextClassLoader().loadClass(controllerPackage + '.' + s.substring(0, s.length() - 6));
classes.add(clazz);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
return classes;
}
public void execute(HttpServletRequest request, HttpServletResponse response) throws Exception {
String requestURI = request.getRequestURI();
Class<?> controller = map.get(requestURI);
Method[] declaredMethods = controller.getDeclaredMethods();
for (Method method : declaredMethods) {
if (requestURI.equals(method.getDeclaredAnnotation(RequestMapping.class).value())) {
Object o = controller.newInstance();
if (o != null) {
Object invoke = method.invoke(o);
if (invoke != null) {//若返回值不是空的,说明需要重定向
String url = (String) invoke;
request.getRequestDispatcher(url).forward(request, response);
}
}
}
}
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
execute(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
execute(req, resp);
}
}
https://www.cnblogs.com/xdp-gacl/p/4101727.html
JVM
https://www.cnblogs.com/chenpt/p/9777367.html
设计模式
单例模式
有三种比较常见的:饿汉式(类加载时就创建该对象,这可能有线程安全问题);普通懒汉式(不带线程安全的措施);DCL懒汉式double check lock(双重检测锁,这个redis分布式锁解决缓存击穿问题很像)
//DCL懒汉式(双重检测锁模式)
public class SingletonDemo3 {
//私有化构造器
private SingletonDemo3() {
}
//volatile的作用是防止指令重排
//在内存中开辟空间;执行构造方法初始化对象;将对象的引用赋值给INSTANCE变量
//在不加volatile的情况下,第2和第3步是有可能发生指令重排的,其他线程就能获取到不完整的对象
private static volatile SingletonDemo3 instance;
public static SingletonDemo3 getInstance() {
if (instance == null) {//若没有这个判断,每个线程
synchronized (SingletonDemo3.class) {
if (instance == null) {
instance = new SingletonDemo3();
}
}
}
return instance;
}
}
操作系统
如何理解虚拟地址空间?
https://www.zhihu.com/question/290504400/answer/1964845950
日志
https://zhuanlan.zhihu.com/p/64353891
https://zhuanlan.zhihu.com/p/62110673
看日志的本质其实是希望程序员在没法调试的时候,能快速定位到问题的手段,所以日志一定要记录关键信息
远程调试
有关远程调试的原理和方法https://blog.csdn.net/qq_37192800/article/details/80761643?utm_source=app&app_version=4.15.2
理解:其实远程调试的时候,只需要保证服务器和本地的代码是一致的就行,启动的时候其实是远程的jvm以debug形式启动了,本地的jvm是没有启动的,只是二者之间通过网络进行了通信罢了
Linux
将任务切换到后台的命令是什么?
杀死前台任务的命令
mac关闭某个端口的进程:
#查看某个端口运行了什么进程
lsof -i tcp:<port>
#根据该进程pid杀死该进程
kill -9 <pid>
ubantu安装java
sudo apt install openjdk-8-jdk
查看云服务器的ip和地区。本机用这个查到的ip也是公网ip吗?
curl cip.cc
回调函数
是什么?
JSP的原理是什么
JSP本质上还是一个servlet,jsp里面可以同时写html标签和java程序,当客户端请求某个jsp的时候,会把这个jsp转换成一个servlet,其html标签和java内容以不同的方式转化为java代码放到该servlet的service方法内部,通过HttpResponse写给浏览器。
https://www.cnblogs.com/xdp-gacl/p/3764991.html
