Java注解与反射07

1. 注解

  1. 对程序起注释作用
  2. 可以被其他程序(如编译器)读取
  3. 约束作用(不符合会报错)

1.1. 内置注解

  • @Override:重写方法
  • @Deprecated:不推荐使用某方法
  • @SupressWarnings:镇压警告

1.2. 元注解

负责注解其他注解(如元注解)

  • @Target
  • @Retention
  • @Document:说明该注解将被包含在javadoc文档中
  • @Inherited:说明子类可以继承父类中的该注解
//Target注解限制注解使用的对象,如方法METHOD,类TYPE等
@Target(value = {ElementType.METHOD,ElementType.TYPE})
//Retention注解限制注解使用的范围,SOURCE<CLASS<RUNTIME
@Retention(value = RetentionPolicy.RUNTIME)
//注解属性中的value可以不写
@interface Myannotation{//在类中不能加public,因为类只能存在一个public类
    //自定义注解Myannotation
}

1.3. 自定义注解

@interface Myannotation{//自定义注解
    String name() default "";
    /*定义注解的属性,不是方法
      加default表示默认取值*/
    String value();//若属性名为value,则可以不加dafault而默认值为""空字符串。
}

2. 反射

Java Reflection:可以使程序在执行期间借助于Reflection API取得任何类的内部信息,并直接操作任意对象的内部属性和方法。

Class:每个类的前缀都是class,这就说明class是一种数据类型,java虚拟机在加载每种class时会实例化一个Class对象(Class本身也是一个类,class Class!),这个Class对象包含了该class(注意,class是数据类型,Class是实例对象!一种class只有一个Class对象)的全部信息,如类名、包名、方法、属性等。那么我们可以利用这个Class对象找到原class的全部属性、方法等,这个过程就叫反射

Class c1 = Class.forName(“”//类路径,如com.stone.reflection.User);

Object类中定义了public final Class getClass()方法,此方法被所有子类继承,该方法返回值的类型是一个Class类。

一个加载的类只有一个class类。

2.1. 得到class类的几种方式

public class Person{
    String name;
    public Person(){
        
    }
}

class Student extends Person{
   public Student(){
       this.name = "学生";
   }
}

class Teacher extends Person{
    public Teacher(){
        this.name = "老师";
    }
}
public class test{
    public static void main(String[] args){
        Person person = new Student();
    }
}
  1. Class c1 = Student.class;
    
  2. Class c2 = Class.forName("com.stone.reflection.Student");//属性值为包名
    
  3. Class c3 = person.getClass();
    
  4. Class c4 = Integer.TYPE;
    
  5. Class c5 = c1.getSuperclass();
    

3. 类加载内存分析

Java内存分为三个区:

  • 方法区(特殊的堆)

类加载后,生成相应的class对象,链接时会将static中的属性设置为默认值,初始化时()会将static中的代码按顺序链接到一起,再顺序执行。

3.1. 类初始化

  • 当主类调用子类时,会先初始化main类,再初始化子类的父类,最后初始化子类
  • 反射类的class对象时初始化类
  • 调用父类的静态属性不会初始化类
  • 实例化引用类的数组时不会初始化类
  • 引用类的被static和final同时修饰的常量不会初始化类

3.2. 类加载器

  • 系统类加载器:加载用户的jar包
  • 扩展类加载器:
  • 引导类加载器:加载核心jar包(我们无法调用)

获取类加载器:

ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
System.out.println(systemClassLoader);
ClassLoader parent = systemClassLoader.getParent();
System.out.println(parent);
ClassLoader parent1 = parent.getParent();
System.out.println(parent1);
/*输出结果:
sun.misc.Launcher$AppClassLoader@18b4aac2
sun.misc.Launcher$ExtClassLoader@1b6d3586
null
*/
System.getProperty("java.class.path")//读取类加载路径

3.3. 获取运行时类的结构

  • 获取类的名字

    • Class c1 = Class.forName("com.stone.refleciton.User");//括号内时类的路径
      System.out.println(c1.getName());
      System.out.println(c1.getSimleName());
      
  • 获取类的属性

    • Field[] declaredFields = c1.getDeclaredFields();//获取类的全部属性
      Field[] field = c1.getFields();//获取类的Public属性
      for(Field field : declaredFields){
          System.out.println(field);
      }
      
  • 获取类的方法

    • Method[] methods = c1.getDeclaredMethods();//获取类的全部方法
      Method[] methods = c1.getMethods();//获取类的public方法
      

3.4. 动态创建对象执行方法

Class c1 = Class.forName("com.stone.reflecttion.User");
  • 通过User的无参构造器创建User类的对象

    • User user = (User)c1.newInstance();//newInstance用于创建c1的实例并强制转换为User类型
      
  • 通过有参构造器进行实例化

    • Constructor constructor = c1.getDeclaredConstructor(String.class,int.class,int.class);
      User user2 = (User)constructor.newInstance("stone",001,18);//通过User类的有参构造器进行实例化对象
      
  • 获取User类的方法

    • User user3 = (User)c1.newInstance();
      Method setName = c1.getDeclaredMethod("setName",String name);
      setName.invoke(user3,"stone");
      System.out.println(user3.getName());
      
  • 获取User类的属性

    • User user4 = (User)c1.Instance();
      Field name = c1.getDeclaredField("name");
      name.setAccessible(true);//关闭程序的安全检测,使得可以读取类的私有属性
      name.set(user4,"stone");
      
  • 当反射较多时,调用setAccessible()关闭Java语言安全检测可以提高运行效率

4. 获取注解信息

@Target(ElementType.FIELD)//注解作用类型为属性
@Retention(RetentionPolicy.RUNTIME)//注解作用范围为程序运行时
@interface Fielstone{//自定义属性注解
    String columnName();
    String type();
    int length();
}

@Target(ElementType.TYPE)//注解作用类型为类
@Retention(RetentionPolicy.RUNTIME)//注解作用范围为程序运行时
@interface Tablestone{//自定义类注解
    String value();
}

@Tablestone("db_stone")
class Student2{
    @Fieldstone(columnName = "db_id",type = "int",length = 10)
    private int id;
    @Fieldstone(columnName = "db_age",type = "int",length = 10)
    private int age;
    @Fieldstone(columnName = "db_name",type = "varchar",length = 3)
    private String name;

    public Student2(){

    }

    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;
    }

    @Override
    public String toString() {
        return "Student2{" +
                "id=" + id +
                ", age=" + age +
                ", name='" + name + '\'' +
                '}';
    }
}

public class Test{
	public void static  main(String[] args){
        Class c1 = Class.forName("com.stone.reflecion.Student2")
        Tablestone tablestone = (Tablestone)c1.getAnnotation(Tablestone.class);//获取Tablestone注解的class类,并实例化
        String value = tablestone.getValue();取得Tablestone类的值
        System.out.println(value);
        
        /*输出结果:
        db_stone
        */
    }
}
posted @ 2021-03-06 15:46  St0n3  阅读(64)  评论(0)    收藏  举报