您的位置 首页 java

Java高级知识注解&反射你忘了吗?

一.注解 annotation

1.什么是注解

2.基本内置注解

@Override 表示这个方法重写了父类的方法

@Deprecated 表示这个方法已经过期,不建议开发者使用

@SuppressWarnings 表示忽略警告信息

3.自定义注解

利用反射读取注解

 public class Test3 {
 
    public static void main(String[] args) {
        try {
            // 1.反射
            Class clazz = Class.forName("com.annotation.Student");
            // 2.获得这个类的注解
            Annotation[] annotations = clazz.getAnnotations();
            for (Annotation annotation:annotations){
                System.out.println(annotation);
            }
            // 3.获得类的注解value的值
            TableKuang table = (TableKuang)clazz.getAnnotation(TableKuang.class);
            System.out.println(table.value());
 
            // 4.获得类指定注解的值
            Field name = clazz.getDeclaredField("name");
            FieldKuang fieldKuang = name.getAnnotation(FieldKuang.class);
            System.out.println(fieldKuang.columnName()+"-->"+fieldKuang.type()+"-->"+fieldKuang.length());
 
 
        } catch (ClassNotFoundException | NoSuchFieldException e) {
            e.printStackTrace();
        }
    }
 
 
}
@TableKuang("db_student")
class Student{
 
    @FieldKuang(columnName = "db_id",type="int",length = 10)
    private int id;
    @FieldKuang(columnName = "db_name",type="varchar",length = 10)
    private String name;
    @FieldKuang(columnName = "db_age",type="int",length = 3)
    private int age;
 
    ......
}
 
// 表名注解
@Target(value = {ElementType.TYPE})
@Retention(value = RetentionPolicy.RUNTIME)
@interface TableKuang{
    String value();
}
 
// 属性注解
@Target(value = {ElementType.FIELD})
@Retention(value = RetentionPolicy.RUNTIME)
@interface FieldKuang{
    String columnName(); // 列名
    String type(); // 类型
    int length();  // 长度
}  

4.元注解

元注解的作用就是负责注解其他注解

@Tartget:用于描述注解的使用范围(Type修饰类、接口或枚举类型;Filed成员变量;Method方法;)

@Retention:表示生命周期(source<class<runtime)

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

@Ducumented:表示注解将被包含在javadoc中

二.反射

这里讲一下 「 运行时 」,.java文件经过javac编译变成. class文件 ,class文件会被 JVM 装载运行。

我记得在工作中,我有一个需求是主系统对用户表、部门表等增量变化的同时要求去增量同步子系统对应的用户表、部门表数据。增量同步的这个工具类就有用到了反射技术。一个好的工具就要兼容各种情况(用户、部门等)。

还有就是SpringMVC中在方法写上对象,传入的参数就会封装到对象上。

这些例子都有涉及到反射:约定大于配置,配置大于硬编码。

2.1 什么是反射

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

加载类之后,在堆内存的方法区就产生了一个Class类型的对象,这个对象就包含了完整的类的结构信息。

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

缺点:对性能有影响,慢于直接执行相同的操作。

2.2 类的加载过程

2.2.1 加载

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

2.2.2 链接

将Java类的二进制代码合并到JVM的运行状态之中的过程

验证:确保加载的类信息符合JVM规范

准备:正式为类变量分配内存并设置类变量默认初始值的阶段(方法区)

解析:虚拟机常量池内的符号引用替换为直接引用的过程

2.2.3 初始化

执行类 构造器 方法的过程

当初始化一个类的时候,如果发现其父类还没有初始化,则需要先触发其父类的初始化

虚拟机会保证一个类的方法在多线程环境中被正确加锁和同步

2.3 类的加载器

类加载器的作用是将class文件字节码内容加载内存中,并将静态数据转换成方法数据结构,然后在堆中生成一个代表这个类的java.lang.class对象,作为方法区中类数据的访问入口

2.4 获取类对象

  • wistchen.getClass()
  • Class.forName(“包名+类名”)
  • Wistchen.class
  • ClassLoader classLoader = this.getClass().getClassLoader(); classLoader.loadClass(className);

2.5 类对象的常用方法

static ClassforName(String name) 返回指定类名name的class对象

Object newInstance() 调用缺省构造函数,返回Class对象的一个实例

getName() 返回此Class对象所表示的实体的名称

Class getSuperClass() 返回当前CLass对象的父类的Class对象

Class[] getinterfaces() 获取当前Class对象的接口

ClassLoader getClassLoader() 返回该类的类加载器

Constructor[] getConstructors() 返回一个包含某些Constructor对象的数组

Method getMethed(String name,Class T) 返回一个Method对象

Field getDeclaredFields() 可以获取本类所有的字段,包括 private 的,但是不能获取继承来的字段。 (注: 这里只能获取到private的字段,但并不能访问该private字段的值,除非加上 setAccessible(true))

Field getField 只能获取public的,包括从父类继承来的字段。

2.5 创建对象

Class pClass = Class.forName(className); 类对象

Constructor c = pClass.getConstructor();构造器

c.newInstance() 通过构造器实例化

2.6 访问属性

 public class TestReflection {
    public static void main(String[] args) {
        Hero hero = new Hero();
        hero.name = "garen";
 
        try{
            Field f1 = hero.getClass().getDeclaredField(("name"));
            f1.set(hero,"teemo");
            System.out.println(hero.name);
        } catch (NoSuchFieldException | IllegalAccessException e) {
            e.printStackTrace();
        }
    }
}
 
class Hero{
    public String name; //为了访问属性,把name修改为public
    public float hp;
    public  int damage;
    public int id;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Hero(){
 
    }
    public Hero(String string) {
        name =string;
    }
 
    @Override
    public String toString() {
        return "Hero [name=" + name + "]";
    }
    public boolean isDead() {
        // TODO Auto-generated method stub
        return false;
    }
    public void attackHero(Hero h2) {
        System.out.println(this.name+ " 正在攻击 " + h2.getName());
    }
}  

2.7 调用方法

 public class TestReflection2 {
    public static void main(String[] args) {
        Hero1 hero1 = new Hero1();
 
        try{
           // 获取这个名字叫做setName,参数类型是String的方法
            Method m = hero1.getClass().getMethod("setName", String.class);
           // 对h对象,调用这个方法            
            m.invoke(hero1,"wistchen");
            System.out.println(hero1.getName());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
 
}
class Hero1 {
    public String name;
    public float hp;
    public int damage;
    public int id;
 
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Hero1(){
 
    }
    public Hero1(String string) {
        name =string;
    }
 
    @Override
    public String toString() {
        return "Hero1 [name=" + name + "]";
    }
    public boolean isDead() {
        // TODO Auto-generated method stub
        return false;
    }
    public void attackHero(Hero h2) {
        // TODO Auto-generated method stub
 
    }
 
}  

学习参考来自:

B站狂神说

公众号Java3y

HOW2J.CN

文章来源:智云一二三科技

文章标题:Java高级知识注解&反射你忘了吗?

文章地址:https://www.zhihuclub.com/200522.shtml

关于作者: 智云科技

热门文章

网站地图