Java基础学习笔记

注解和反射

注解和反射

注解Annotation

不是程序本身,但是可以对程序进行解释

格式: @注释名

内置注解:

@Override 重写超类

@Deprecated 已废弃的 不推荐使用(仍然可以用)

@SuppressWarnings 镇压警告(必须传参数才能使用)

元注解:

负责注解其他注解的注解

@Target ()表示注解可以用在哪些地方

@Retention 表示在什么地方还有效

@Documented 是否生成在JAVAdoc中

@Inherited 表示子类可以继承父类的注解

@MyAnnotation
public class Demo_01 {
}
@Target(value={ElementType.METHOD,ElementType.TYPE})//用在方法上   和类上
@Retention(value= RetentionPolicy.RUNTIME)//表示注解在什么地方还有效
@Documented   //表示是否将我们的注解生成在JAVAdoc中
@Inherited     //子类可以继承父类的注解
@interface MyAnnotation{
}
自定义注解
@interface MyAnnotation{
    //注解的参数: 参数类型 +参数名()
    String name() default"";
    int age() default 0;
    int id() default -1;//默认值为-1代表不存在  
    String[] schools() default{"你好","自定义"}
}

反射 Reflection

反射是Java被视为动态语言的关键,反射机制允许程序在执行期间借助Reflection 取得任何类的内部信息,并且能直接操作任意对象的内部属性及方法

优点:动态创建对象和编译,体现出很大的灵活性

缺点:影响性能

Class类的获取
public class Demo_03 {

    public static void main(String[] args) throws ClassNotFoundException {
        Person person=new Student();
        //方式1:通过对象获取
        Class c1=person.getClass();
        System.out.println(c1.hashCode());
        //方式2:forName获取
        Class c2=Class.forName("day_04.Student");
        System.out.println(c2.hashCode());
        //方式3:通过类名。class获取
        Class c3=Student.class;
        System.out.println(c3.hashCode());
        //方法4:基本内置类型和包装类都有一个Type属性
        Class<Integer> c4=Integer.TYPE;
        System.out.println(c4.hashCode());
        //获取父类类型
        Class c5= c1.getSuperclass();
    }
}
class Person{
  String name;
    int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public Person() {
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
class Student extends Person{
    public Student(){
        this.name="学生" ;
    }
    }
class Teacher extends Person{
    public Teacher(){
        this.name="老师" ;
    }
}

image-20210426112545829

所有类型的Class类
import java.lang.annotation.ElementType;

public class Demo_04 {
    public static void main(String[] args) {
        Class c1=Object.class;//类
        Class c2=Comparable.class;//接口
        Class c3=String[].class;//一维数组
        Class c4=int[][].class;//二维数组
        Class c5=Override.class;//注解
        Class c6= ElementType.class;//枚举
        Class c7=Integer.class;//基本数据类型
        Class c8=void.class;//void
        Class c9=Class.class;//Class本身

        System.out.println(c1);
        System.out.println(c2);
        System.out.println(c3);
        System.out.println(c4);
        System.out.println(c5);
        System.out.println(c6);
        System.out.println(c7);
        System.out.println(c8);
        System.out.println(c9);
//只要元素类型与维度一直,就是一个Class
int[]a=new int[10];
int[]b=new int[100];
        System.out.println(a.getClass().hashCode());
        System.out.println(b.getClass().hashCode());
    }
}

image-20210426113427699

类加载内存分析

image-20210426113637029

了解类的加载过程:

类的加载Load-------> 类的链接Link--------->类的初始化Initialize

加载:将class文件字节码内容加载到内存中,并将这些静态数据转化成方法区的运行时数据结构,然后生成一个代表这个类的 java.lang.Class对象

链接:将java类的二进制代码合并到JVM运行状态中的过程

  • 验证:确保加载的类信息符合JVM规范
  • 准备:正式为类变量(static)分配内存并设置类变量默认初始值,这些内存都将在方法区中进行分配
  • 解析:虚拟机常量池内的符号引用代替为直接引用的过程

初始化

  • 执行类构造器()方法的过程,类构造器是构造类信息的,不是构造类对象的
  • 当初始化一个类时,如果父类没有被初始化,则先出发父类的初始化
  • 虚拟机会保证一个类的client方法在多线程环境中被正确的加锁和同步

类的加载过程

public class Demo_05 {
    public static void main(String[] args) {
        A a=new A();
        System.out.println(A.m);
    }
/**
 * 1,加载到内存,产生一个类对应的class对象
 * 2,链接,链接后m=0
 * 3,初始化System.out.println("A类的静态代码初始化");
 *          m=300;
 *          m=100;
 *          ---->m=100
 *
 */
}
class A{
    static {
        System.out.println("A类的静态代码初始化");
         m=300;
    }
    static int m=100;
    public A(){
        System.out.println("A的无参构造初始化");
    }
}

image-20210426120554488

什么时候会发生类的初始化

image-20210426120901687

获取类运行时的完整结构
public class Test_02 {
    //获取类的信息
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException {
        Class c1=Class.forName("day_04.User");
        //类名:
        System.out.println(c1.getName());
        System.out.println(c1.getSimpleName());
        //类的属性
      Field[] fields= c1.getFields();
        for (Field field : fields) {
            System.out.println(field);

        }

        //获取指定属性的值
        Field name=c1.getDeclaredField("name");
        System.out.println(name);
        //获取类的方法
        System.out.println("==============================");
        Method[] methods = c1.getMethods();
        for (Method method : methods) {
            System.out.println("正常的"+method);

        }
        methods=c1.getDeclaredMethods();//获取本类的所有方法
        for (Method method : methods) {
            System.out.println("getDecleredMethods:"+method);
        }

        //获取指定的方法
        Method getName = c1.getMethod("getName", null);
        Method setName = c1.getMethod("setName", String.class);

        //获得指定的构造器
        System.out.println("===========================");
        Constructor[] constructors = c1.getConstructors();
        for (Constructor constructor : constructors) {
            System.out.println(constructor);
        }
        Constructor[] declaredConstructors = c1.getDeclaredConstructors();
        for (Constructor declaredConstructor : declaredConstructors) {
            System.out.println(declaredConstructor);
        }

    }
}

image-20210427131758281

动态创建对象执行方法
public class Demo_07 {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
        Class c1=Class.forName("day_04.User");
        //构造一个对象
        User user =(User) c1.newInstance();//本质是是调用了类的无参构造器
        System.out.println(user);
        System.out.println("==================");
        //通过构造器创建方法
        Constructor constructor=c1.getDeclaredConstructor(String.class,int.class,int.class);
        User user1=(User)constructor.newInstance("麒",001,18);
        System.out.println(user1);
        System.out.println("====================");
        //通过反射获取一个方法
        User user2=(User)c1.newInstance();
        Method setName=c1.getDeclaredMethod("setName", String.class);
        setName.invoke(user2,"麒0");//invork (对象,方法的值)
        System.out.println(user2.getName());
        System.out.println("======================");
        //通过反射操作属性
        User user3=(User) c1.newInstance();
        Field name= c1.getDeclaredField("name");
        //关闭权限检测   不能直接操作私有属性,需要关闭
        name.setAccessible(true);
        name.set(user3,"麒1");
        System.out.println(user3);

    }
}

image-20210427134541669

性能对比分析
public class Demo_08 {
    public static void test01(){
        User user=new User();
        long startTime=System.currentTimeMillis();
        for(int i=0;i<=1_000_000_000;i++){
            user.getName();
        }
        long endTime=System.currentTimeMillis();
        System.out.println("普通方法执行10亿次:"+(endTime-startTime)+"ms");
    }
    public static void test02() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        User user =new User();
        Class c1=user.getClass();
        Method getName = c1.getDeclaredMethod("getName", null);
        long startTime=System.currentTimeMillis();
        for(int i=0;i<=1_000_000_000;i++){
            getName.invoke(user,null);
        }
        long endTime=System.currentTimeMillis();
        System.out.println("反射方法执行10亿次:"+(endTime-startTime)+"ms");

    }
    public static void test03() throws InvocationTargetException, IllegalAccessException, NoSuchMethodException {
        User user =new User();
        Class c1=user.getClass();
        Method getName = c1.getDeclaredMethod("getName", null);
        getName.setAccessible(true);
        long startTime=System.currentTimeMillis();
        for(int i=0;i<=1_000_000_000;i++){
            getName.invoke(user,null);
        }
        long endTime=System.currentTimeMillis();
        System.out.println("关闭检测反射方法执行10亿次:"+(endTime-startTime)+"ms");
    }

    public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
        test01();
        test02();
        test03();
    }
}

image-20210427135911541

通过反射操作注解

ORM:对象关系映射 Object Relation Mapping

public class Demo_10 {    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {        Class c1 = Class.forName("day_04.Student2");        //通过发射获得注解        Annotation[] annotations = c1.getAnnotations();        for (Annotation annotation : annotations) {            System.out.println(annotation);        }        //获取注解value值        Table_phq table_phq= (Table_phq)c1.getAnnotation(Table_phq.class);        String value=table_phq.value();        System.out.println(value);        //获取类指定的注解        Field f=c1.getDeclaredField("name");        Field_phq annotation = f.getAnnotation(Field_phq.class);        System.out.println(annotation.columnName());        System.out.println(annotation.length());        System.out.println(annotation.type());    }}@Table_phq("db_student")class Student2{    @Field_phq(columnName = "db_id",type="int",length = 10)    private int id;    @Field_phq(columnName = "db_age",type="int",length = 10)    private int age;    @Field_phq(columnName = "db_name",type="String",length = 10)    private String name;    public Student2(int id, int age, String name) {        this.id = id;        this.age = age;        this.name = name;    }    public int getId() {        return id;    }    public void setId(int id) {        this.id = id;    }    public int getAge() {        return age;    }    public void setAge(int age) {        this.age = age;    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public Student2() {    }    @Override    public String toString() {        return "Student2{" +                "id=" + id +                ", age=" + age +                ", name='" + name + '\'' +                '}';    }}//类名的注解@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@interface Table_phq{    String value();}//属性的注解@Target(ElementType.FIELD)@Retention(RetentionPolicy.RUNTIME)@interface Field_phq{    String columnName();    String type();    int length();}

image-20210427144005577

留言