Java基础

泛型

用泛型写个快排

  1. public class QuickSort01 {
  2. public static void main(String[] args) {
  3. // Integer array[] = {2,1,4,5,0};
  4. String array[] = {"2","1","4","5","0"};
  5. // ListNode listNode = new ListNode(2);
  6. // ListNode[] array = {listNode};
  7. quickSort(array);
  8. for (int i = 0; i < array.length; i++) {
  9. System.out.println(array[i]);
  10. }
  11. }
  12. //你只能传一个实现了Comparable接口的类型,比如Integer/String/Long...
  13. public static <T extends Comparable> void quickSort(T [] array){
  14. quickSort(array,0,array.length-1);
  15. }
  16. private static <T extends Comparable> void quickSort(T[] array, int start, int end) {
  17. int index = getIndex(array, start, end);
  18. if(index>start){
  19. quickSort(array,start,index-1);
  20. }
  21. if(index<end){
  22. quickSort(array,index+1,end);
  23. }
  24. }
  25. public static <T extends Comparable> int getIndex(T[] array,int start,int end){
  26. T pivot = array[start];
  27. while(start<end){
  28. while (start<end&&array[end].compareTo(pivot)>=0){
  29. end--;
  30. }
  31. array[start] = array[end];
  32. while (start<end&&array[start].compareTo(pivot)<=0){
  33. start++;
  34. }
  35. array[end] = array[start];
  36. }
  37. array[start] = pivot;
  38. return start;
  39. }
  40. }

注解

@Retention作用是定义被它所注解的注解保留多久,一共有三种策略,定义在RetentionPolicy枚举中.
从注释上看:
source:注解只保留在源文件,当Java文件编译成class文件的时候,注解被遗弃;被编译器忽略
class:注解被保留到class文件,但jvm加载class文件时候被遗弃,这是默认的生命周期
runtime:注解不仅被保存到class文件中,jvm加载class文件之后,仍然存在

强制类型转换

java中引用类型的强制转换:自下而上转型是顺其自然的,因为父类的功能本来就少,所以无需强制转换,比如Fruit apple = new Apple()就是一种向上转换;但自上而下转换是需要强制转换的,强制转换能否成功,要看被强制转换的那个对象本质上是个什么对象(由生成它的构造器决定)。

  1. @Test
  2. public void test01(){
  3. Fruit fruit = hello();
  4. Apple apple = (Apple) fruit;
  5. System.out.println(apple);
  6. }
  7. public Fruit hello(){
  8. //这种不会报错,因为使用的构造器决定了返回值本质上是一个Apple
  9. // Apple apple = new Apple();
  10. // apple.name = "apple";
  11. // apple.apple = true;
  12. //这种会报错,因为使用的构造器决定了返回值本质上是一个Fruit
  13. Fruit apple = new Fruit();
  14. apple.name="apple";
  15. return apple;
  16. }

反射实战

实现一个简易的@Controller和@RequestMapping
image.png

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
  5. version="4.0">
  6. <servlet>
  7. <servlet-name>MyServlet</servlet-name>
  8. <servlet-class>com.example.servlettest.MyServlet</servlet-class>
  9. <init-param>
  10. <description>配置要扫描包及其子包, 如果有多个包,以逗号分隔</description>
  11. <param-name>controllerPackage</param-name>
  12. <param-value>com.example.servlettest.controller</param-value>
  13. <!-- <param-value>me.gacl.web.controller</param-value> -->
  14. </init-param>
  15. <load-on-startup>1</load-on-startup>
  16. </servlet>
  17. <servlet-mapping>
  18. <servlet-name>MyServlet</servlet-name>
  19. <!-- 拦截所有以.do后缀结尾的请求 -->
  20. <url-pattern>*.xjf</url-pattern>
  21. </servlet-mapping>
  22. </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