Skip to content

Latest commit

 

History

History
926 lines (704 loc) · 26.1 KB

泛型.md

File metadata and controls

926 lines (704 loc) · 26.1 KB
System.out.println(Class.forName("java.lang.String").getClassLoader());

泛型

1.不使用泛型

不使用泛型从iterator读取的东西都是Object类型。如果不使用泛型,必须使用instanceof来判断然后强制转型才可以。

package cn.text.hashmap;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

public class Text02 {
    public static void main(String[] args) {
        Collection coll = new ArrayList();
        Father father = new Father();
        coll.add(father);
        Iterator iterator = coll.iterator();
        Object next = iterator.next();
	    //取出来的都是object类型的,没有run()方法,只能加强制转换
        if (next instanceof Father) {
            Father father1 = (Father)next;
            father1.run();
        }
    }
}

class Father{
    void run(){
        System.out.println("父亲在跑步");
    }
}

2.使用泛型

使用泛型之后只能在集合中储存限定的数据,而且迭代取出来的也是限定类,不用加强转

package cn.text.hashmap;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

public class Text02 {
    public static void main(String[] args) {
        Collection<Father> coll = new ArrayList<Father>();
        Father father = new Father();
        coll.add(father);
        Iterator<Father> iterator = coll.iterator();
        Father next = iterator.next();
        //直接取出来的就是Father类,而不是Object类
        next.run();
    }
}

class Father{
    void run(){
        System.out.println("父亲在跑步");
    }
}

3.泛型的自动推断

package cn.text.hashmap;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

public class Text02 {
    public static void main(String[] args) {
        // new ArrayList<>()的<>中的限定类可以不写,它会自动推断
        Collection<Father> coll = new ArrayList<>();
        Father father = new Father();
        coll.add(father);
        Iterator<Father> iterator = coll.iterator();
        Father next = iterator.next();
        next.run();
    }
}

class Father{
    void run(){
        System.out.println("父亲在跑步");
    }
}

IO

1.分类

1.按流的方向

  • 当数据流从内存流出到输出
  • 当数据流流入内存加流入

2.按类型

  • 字节流:按照字节的方式读取数据,一次读取一个字节,等同于读取8个二进制,这种流是万能的,什么都可以读。比如:文本、视频、音频、图片
  • z字符流:按照字符来读取数据,一次读取一个字符,只能读取纯文本文件,不能读取视频、音频、图片

3. 流的四大家族

  • InputStream(输入字节流)
  • OutputStream(输出字节流)
  • reader(输入字符流)
  • writer(输出字符流)

4.资源绑定器

  • 必须用.properties结尾
package cn;
import java.util.ResourceBundle;
public class reflectJava {
    public static void main(String[] args) {
        //不需要流对象,直接用ResourceBundle.getBundle获取properties文件,读取里面的key-value
        ResourceBundle resoure = ResourceBundle.getBundle("db");
        System.out.println(resoure.getString("username"));
    }
}

注解

1. 注解理解

  • 编译器可以检查带注解的成员、属性、类等,让成员、属性、类等做一些限制。
  • 可以起到一个flag的作用,配合反射机制完成其他功能。

2.注解的中定义的属性类型

byte short int long float double boolean char String Class Annontation enum 以及以上的类型数组

这是定义的注解的.java文件

package cn.text.hashmap;
import java.lang.annotation.*;
//这是定义的注解
@Target({ElementType.TYPE,ElementType.FIELD,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface MyAnnontation {

    String s1();
    boolean flag();
    Myenum myEnum();  //定义的枚举属性
    MyAnnontation02 myAnnontation02(); //定义的注解属性
    Class classtype(); 
   
}

@Target({ElementType.TYPE,ElementType.FIELD,ElementType.METHOD})
@interface MyAnnontation02 {
}

enum Myenum{
    TEXT01;
}

这是定义的tAnnotationText.java文件

public class AnnotationText {
    @MyAnnontation(s1 = "1111",flag = true,myEnum = Myenum.TEXT01, classtype = String.class,myAnnontation02 = @MyAnnontation02)
    public static void main(String[] args) {
        System.out.println("111111111");
    }
}

类加载器

1. 层级关系

引导类加载器(爷)

扩展类加载器(爸)

系统类加载器(孙子)

2. 加载机制

  • 先去引导类加载器加载,找到直接返回。
  • 引导类加载器找不到再去扩展类加载器加载,找到直接返回。
  • 扩展类加载器找不到直接去系统加载器加载。

3.负责加载的内容

  1. 引导类加载器

负责加载rt.jar里面的类加载

//这是引导类加载器,无法直接获取
System.out.println(Class.forName("java.lang.String").getClassLoader());
//输出位null
  1. 扩展类加载器

加载ext包里面的类

System.out.println(ClassLoader.getSystemClassLoader().getParent());
//输入为sun.misc.Launcher$ExtClassLoader@1b6d3586
  1. 系统类加载器

加载classpath路径里面的class

System.out.println(ClassLoader.getSystemClassLoader());
//输出为sun.misc.Launcher$AppClassLoader@18b4aac2

反射

1.反射作用

反射可以操作整个字节码文件(.class文件),可以读和修改字节码文件。

2.通过反射获取类

//这是第一种方法
try {
    Class c3 = Class.forName("java.util.ArrayList");
} catch (ClassNotFoundException e) {
    e.printStackTrace();
}
//这是第二种方法
String s = "";
Class c1 = s.getClass();
//这是第三种方法
Class c2 = String.class;

3. 反射获取字节码的内存图

通过反射获取的相同字节码只在jvm加载一份

public class text{
    public static void main(String[] args) {
        String s1 = "";
        Class c1 = s1.getClass();
        Class c2 = String.class;
        if (c1==c2){
            System.out.println("内存地址一样");
        }
    }
}

image-20210401135856861

4.反射优点

  • 增加了代码的灵活性、扩展性。

通过加载配置文件中的类名来创建对象,如果需要创建别的对象,只需要改变配置文件的类名就欧克,不要去动代码里面的东西。增加了代码的灵活性。

如果使用new来创建对象,当需要创建别的对象时你需要去改变代码,这样就降低了代码的可扩展性。

package cn;
import java.util.Date;
import java.util.ResourceBundle;

public class ReflectJava {
    public static void main(String[] args) {
 		
        ResourceBundle resoure = ResourceBundle.getBundle("cn");
        String className = resoure.getString("className");
        try {
            Class c = Class.forName(className);
            Date o = (Date)c.newInstance();
            System.out.println(o);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        }

    }
}

5.反射操作

1.字段

  • 操作类的字段的名字、类型、修饰符
package cn;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
public class ReflectJava03 {
    public static void main(String[] args) {
        try {
            Class c = Class.forName("cn.User");
            
            //根据该字段可以创建类的对象
            Field name = c.getDeclaredField("name");
            User user = (User)name.get(c);
            
            
            System.out.println(c.getName()); //c.getName() 获取类的名字
            System.out.println(c.getSimpleName());//获取类的简单名字 
            System.out.println(c.getField("age"));//获取类对象只有public修饰的字段
            System.out.println(c.getFields());//获取类对象只有public修饰的所有字段
            System.out.println(c.getDeclaredField("age"));//获取类对象的age字段
            Field[] df = c.getDeclaredFields();//获取类对象的所有字段
            for (Field f : df){
                //获取该申明该字段的类
                System.out.println("f.getDeclaringClass().getName()===="+f.getDeclaringClass().getName());
                //获取该字段的类型
                //如果类型中带泛型修饰,则只会返回类型,不会返回泛型
                System.out.println("f.getType()"+f.getType());
                //获取该字段的类型
                //如果类型中带泛型修饰,该字段的类型和泛型全部返回
                System.out.println("f.getGenericType()"+f.getGenericType());
                //获取该字段的名字
                System.out.println(f.getName());
                //f.getModifiers()获取该字段的修饰符,返回的是修饰符的对应数字。
                //可以使用Modifier.toString("修饰符代表的数字参数")把数字转换成修饰符
                System.out.println(Modifier.toString(f.getModifiers()));
                
                System.out.println("f.getAnnotatedType()"+f.getAnnotatedType());              
                System.out.println("===========================");
            }
        } catch (ClassNotFoundException  e) {
            e.printStackTrace();
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
    }
}



class User{
    public static boolean sex;
    public int age;
    private String name;
    String addr;
    protected int heiht;
}
  • 对象的赋值和读取
package cn;
import java.lang.reflect.Field;
public class ReflectJava04 {
    public static void main(String[] args) {
        try {
            Class c = Class.forName("cn.User");
            User user = (User)c.newInstance();
            Field name = c.getDeclaredField("name");
            //设置为true才可以操作对象的私有属性
            name.setAccessible(true);
            name.set(user,"1111");
            System.out.println(name.get(user));
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
    }
}

class User {
    @Text(name = "wangwu")
    public static boolean sex;
    public static int age = 18;
    private static String name = "jiruixin";
    String addr;
    protected int heiht;
    List<Integer> list;
}
  • 操作类字段的注解
package cn;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.lang.reflect.Type;

public class ReflectJava03 {
    public static void main(String[] args) {
        try {
            Class c = Class.forName("cn.User");
            Field sex = c.getDeclaredField("sex");
   		    //获取该字段的注解的对象
            //获取到该对象就可以查看该对象的信息
            Text annotation = sex.getAnnotation(Text.class);
            //查看该字段注解的类型,返回的是Class
            System.out.println(annotation.annotationType());
             //获取该字段的所有注解的对象
            Annotation[] annotations = sex.getAnnotations();
            //Annotation[] da2 = sex.getDeclaredAnnotations();
            //System.out.println("1"+sex.getAnnotatedType());
            for (Annotation a:annotations){
                Text c1 = (Text) a;
                System.out.println("注解数组"+c1.name());
            }
        } catch (ClassNotFoundException  e) {
            e.printStackTrace();
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
    }
}

class User {
    @Text(name = "wangwu")
    public static boolean sex;
    public static int age = 18;
    private static String name = "jiruixin";
    String addr;
    protected int heiht;
    List<Integer> list;

}

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.ANNOTATION_TYPE,ElementType.FIELD})
@interface Text{
    String name() ;
}

2.方法

  • 获取方法的基本信息
package cn;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class ReflectJava04 {
    public static void main(String[] args) {
        try {
            Class c = Class.forName("cn.User");
            Method[] methods2 = c.getDeclaredMethods();
            for (Method m : methods2){
                //拿到方法的所有参数,进行遍历得到每个参数
                Class[] p = m.getParameterTypes();
                for (Class c1 : p){
                    System.out.println("p  "+c1.getSimpleName());
                }
                //方法的返回值的Class
                System.out.println("1  "+m.getReturnType());     
                //方法的名字
                System.out.println("3  "+m.getName());
                System.out.println("------------------");
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}




import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.List;
class User {
  
    public String login(String username, String admin){
        if ("admin".equals(username)&& "123".equals(admin)){
            return "登录成功";
        }else {
            return "登陆失败";
        }
    }

    private static String login4(String username, String admin){
        if ("admin".equals(username)&& "123".equals(admin)){
            return "登录成功";
        }else {
            return "登陆失败";
        }
    }

}
  • 调用对象的方法
package cn;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class ReflectJava04 {
    public static void main(String[] args) {
        try {
            Class c = Class.forName("cn.User");
            
            User user = (User)c.newInstance();
            Method login = c.getDeclaredMethod("login4", String.class, String.class);
            //操作私有需要把setAccessible设为true
            login.setAccessible(true);
            System.out.println(login.invoke(user,"admin","123"));
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }
}


import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.List;
class User {
  
    public String login(String username, String admin){
        if ("admin".equals(username)&& "123".equals(admin)){
            return "登录成功";
        }else {
            return "登陆失败";
        }
    }

    private static String login4(String username, String admin){
        if ("admin".equals(username)&& "123".equals(admin)){
            return "登录成功";
        }else {
            return "登陆失败";
        }
    }

}
  • 调用构造参数创建对象
package cn;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public class ReflectJava05 {
    public static void main(String[] args) {
        try {
            Class c = Class.forName("cn.User");
            //java的函数比较是名字和参数列表,有一个一样就是不一样
            //调用什么样的构造函数就看你参数
            Constructor dc = c.getConstructor(String.class);
            User user = (User)dc.newInstance("jiruixin");

        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }
}

可变数组

类型...是可变长度参数,可以用数组给可变长度参数传值

package com.company;
import  java.lang.String;
public class Main {

    public static void main(String[] args) {
        String[] strings = {"s1", "s2", "s3","s4"};
        //用数组给User的构造函数传值
        User user = new User(strings);
    }
}


class User{
    //用可变长度参数来接受数组
    public User(String... ss){
        for(String s : ss){
            System.out.println(s);
        }
        System.out.println(ss);
    }
}

springboot启动

1.启动类

这是springboot的启动类

@SpringBootApplication
public class FirstdemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(FirstdemoApplication.class, args);
    }
}

2. 创建SpringApplication对象

SpringApplication.run进入一下代码

//首先进入这个方法
//Class<?> primarySource = FirstdemoApplication.class
//String... args = args(main方法的参数)
public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {
    //调用下面的run方法
    return run(new Class[]{primarySource}, args);
}

//Class<?> primarySource = FirstdemoApplication.class
//String... args = args(main方法的参数)
public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
    //这是两步,第一步是实例SpringApplication对象,第二步是调用run方法
    return (new SpringApplication(primarySources)).run(args);
}

进入SpringApplication对象的构造方法

//首先进入这个方法
//Class<?>... primarySources = FirstdemoApplication.class
public SpringApplication(Class<?>... primarySources) {
    //调用下面的构造方法
    this((ResourceLoader)null, primarySources);
}

//ResourceLoader resourceLoader = null
//Class<?>... primarySources = FirstdemoApplication.class
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
    
    /****************************初始化一些配置*****************************************/
    this.sources = new LinkedHashSet();
    this.bannerMode = Mode.CONSOLE;
    this.logStartupInfo = true;
    this.addCommandLineProperties = true;
    this.addConversionService = true;
    this.headless = true;
    this.registerShutdownHook = true;
    this.additionalProfiles = Collections.emptySet();
    this.isCustomEnvironment = false;
    this.lazyInitialization = false;
    this.applicationContextFactory = ApplicationContextFactory.DEFAULT;
    this.applicationStartup = ApplicationStartup.DEFAULT;
    this.resourceLoader = resourceLoader;
    Assert.notNull(primarySources, "PrimarySources must not be null");
    /****************************初始化一些配置*****************************************/
    
    //******************重要**************************************//
    //这是把run方法中class的类的数组变成了set列表。
  
    this.primarySources = new LinkedHashSet(Arrays.asList(primarySources));
    //判断是否是web应用
    this.webApplicationType = WebApplicationType.deduceFromClasspath();
    
    this.bootstrappers = new ArrayList(this.getSpringFactoriesInstances(Bootstrapper.class));
    
    //把META-INF文件下的spring.factories里面的ApplicationContextInitializer类实例化并且保存在列表里
    //?有什么用
    this.setInitializers(this.getSpringFactoriesInstances(ApplicationContextInitializer.class));
    
    //把META-INF文件下的spring.factories里面的ApplicationListener类实例化并且保存在列表里
    //?有什么用
    this.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class));
    
    //去堆栈信息里查找有main方法的类
    this.mainApplicationClass = this.deduceMainApplicationClass();
    //******************重要**************************************//
    
    //到这里对象的创建全部完成,剩下就是调用该对象的run方法
}

3. 调用SpringApplication.run()方法

调用SpringApplication.run()方法

public ConfigurableApplicationContext run(String... args) {
    StopWatch stopWatch = new StopWatch();
    stopWatch.start();
    DefaultBootstrapContext bootstrapContext = this.createBootstrapContext();
    ConfigurableApplicationContext context = null;
    this.configureHeadlessProperty();
    SpringApplicationRunListeners listeners = this.getRunListeners(args);
    listeners.starting(bootstrapContext, this.mainApplicationClass);

    try {
        ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
        /*****************************重要**************************************************/
        //获取应用的环境
        ConfigurableEnvironment environment = this.prepareEnvironment(listeners, bootstrapContext, applicationArguments);
		
        //忽略环境里的一些信息
        this.configureIgnoreBeanInfo(environment);

        //打印图标
        Banner printedBanner = this.printBanner(environment);

        //创建上下文容器
        context = this.createApplicationContext();

        //设置应用启动器
        //?不理解
        context.setApplicationStartup(this.applicationStartup);

        /*****************************非常重要********************************************/
        //这是注册了主类到容器里
        this.prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
        //这里面是注册配置类和实例化
        this.refreshContext(context);
        /*****************************非常重要********************************************/
        
        this.afterRefresh(context, applicationArguments);
        stopWatch.stop();
        /*****************************重要**************************************************/
        if (this.logStartupInfo) {
            (new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), stopWatch);
        }

        listeners.started(context);
        this.callRunners(context, applicationArguments);
    } catch (Throwable var10) {
        this.handleRunFailure(context, var10, listeners);
        throw new IllegalStateException(var10);
    }

    try {
        listeners.running(context);
        return context;
    } catch (Throwable var9) {
        this.handleRunFailure(context, var9, (SpringApplicationRunListeners)null);
        throw new IllegalStateException(var9);
    }
}
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);

StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
// Invoke factory processors registered as beans in the context.
//注册bean的类
invokeBeanFactoryPostProcessors(beanFactory);

// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
beanPostProcess.end();

// Initialize message source for this context.
initMessageSource();

// Initialize event multicaster for this context.
initApplicationEventMulticaster();

// Initialize other special beans in specific context subclasses.
//初始化tomcat
onRefresh();

// Check for listener beans and register them.
registerListeners();

// Instantiate all remaining (non-lazy-init) singletons.
//完成实例化
finishBeanFactoryInitialization(beanFactory);

// Last step: publish corresponding event.
finishRefresh();

springboot使用

1.热部署

  1. pom.xml增加这个配置文件
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-devtools</artifactId>
    <optional>true</optional>
</dependency>
  1. 在file -> settings -> compiler

image-20210405085406277

  1. 在shift + ctrl +alt + /(问号按键下面的斜杠)点击registry

image-20210405085524775

  1. 勾选里面的run,然后重启IDEA

image-20210405085713585

2. 对application.yml对热部署配置

spring:
  main:
    # 这是让application的延迟对象的实例化,只有用的时候才实例化对象
    lazy-initialization: true
  devtools:
    restart:
      # 开启热部署,一般不用配置,默认开启,可以使用这个来关闭
      enabled: true
      # 只有这个文件里面的东西改变了才会重启
      trigger-file: "aa.reloadtrigger"
      # 没搞明白
      log-condition-evaluation-delta: false