Java基础——注解和反射

Java基础——注解和反射

一、注解

1、注解入门

1.注解Annotation是JDK5.0新增的功能
2.Annotation的作用:
①不是程序本身,可以对程序做出解释(和注释(comment)没什么区别)
可以被其他程序(例如:编译器等)读取
3.Annotation的格式:“@注释名”
例如:@SuppressWarning(value=“unchecked”)
4.Annotation可以附加在package,class,method,field上面,给他们添加额外的辅助信息。

2、内置注解

1.@Override:此注解只适用于修饰方法,表明一个方法声明打算重写父类中的另一个方法声明。
2.@Deprecated:此注解可以用于修饰方法,属性,类,表示不鼓励程序员使用这样的元素。
3.@SuppressWarnings:用来抑制编译时的警告信息。
与前两个注解不同,需要添加一个参数才能正确使用
例如:@SuppressWarnings(“all”)、@SuppressWarnings(“unchecked”)、@SuppressWarnings(value={“uncheked”,“deprecation”})

3、元注解,自定义注解

1)元注解

1.meta-annotation元注解的作用就是负责注解其他注解
2.@Target:用于描述注解的使用范围(即:被描述的注解可以用在什么地方)
3.@Retention:表示需要在什么级别保存该注解信息,用于描述注解的声明周期(RUNTIME > CLASS >SOURCE)
4.@Documented:说明该注解将被包含在javadoc中
5.@Inherited:说明子类可以继承父类中的该注解

2)自定义注解

1.@interface用来声明一个注解,格式:public @interface 注解名{ 定义内容 }
2.其中的每个方法实际上是声明了一个配置参数
3.方法的名称就是参数的名称
4.返回值类型就是参数的类型(返回值只能是基本类型,Class,String,enum)
5.可以通过default来声明参数的默认值
6.如果只有一个参数成员,一般参数名为value
7.注解元素必须要有值,我们定义注解元素时,经常使用空字符串,0作为默认值

public class test03 {
    @MyAnnotation(name = "张三", age = 14)
    public void test01(){

    }
    @MyAnnotation01("ABC")
    public void test02(){

    }
}

@Target(value = ElementType.METHOD)
@Retention(value = RetentionPolicy.RUNTIME)
@interface MyAnnotation{
    //注解的参数:参数类型 参数名();
    String name();
    int age();
    int id() default 001;
}
@Target(value = ElementType.METHOD)
@Retention(value = RetentionPolicy.RUNTIME)
@interface MyAnnotation01{
    String value();
}

二、反射

1、Java反射机制概述

1)静态 VS 动态语言

1.动态语言:在运行时代码可以根据某些条件改变自身结构。主要动态语言:Object-C、C#、JavaScript、PHP、Python等
2.静态语言:运行时结构不改变的语言。如Java、C、C++

2)Java Reflection

1.反射机制循序程序在执行期间借助于Reflection APT获取任何类的内部信息,并能直接操作任意对象的内部属性及方法
2.加载完类之后,在堆内存的方法区中就产生了一个Class类型的对象(一个类只有一个Class对象),这个对象就包含了完整的类的结构信息。我们可以通过这个对象看到类的结构
3.实例化对象
①正常方式:引入需要的“包类”名称——>通过new实例化——>取得实例化对象
②反射方式:实例化对象——>getClass()方法——>得到完整的“包类”名称

3)反射优点和缺点

1.优点:可以实现动态创建对象和编译,具有灵活性
2.缺点:对性能有影响。慢于直接执行相同的操作

2、理解Class类并获取Class实例

1)Class类

1.Class本身是一个类
2.Class对象只能由系统建立对象
3.一个加载的类在JVM中只会有一个Class实例
4.一个Class对象对应的是一个加载到JVM中的一个class文件
5.每个类的实例都会记得自己是由哪个Class实例所生成
6.通过Class可以完整地得到一个类中的所有被加载的结构
7.Class类是Reflection的根源,针对任何你想动态加载、运行的类,唯有先获得相应的Class对象

2)获取Class类的实例

1、如果已知具体的类,通过类的class属性获取,该方法最为安全可靠,性能最高
Class clazz = Person.class;
2、已知某个类的实例,调用该实例的getClass()方法获取Class对象
Class clazz = person.getClass();
3、已知一个类的全类名,且该类在类路径下,可通过Class类的静态方法forName()获取,有ClassNotFoundException异常
Class clazz = Class.forName(“demo01.Student”);
4、内置基本数据类型可以直接用类名.Type
5、还可以利用ClassLoader

public class Test01 {
    public static void main(String[] args) {
        Person p = new Student();
//        如果已知具体的类,通过类的class属性获取,该方法最为安全可靠,性能最高
//        Class clazz = Person.class;
        Class c1 = Student.class;
        System.out.println(c1);
        System.out.println(c1.hashCode());
//        已知某个类的实例,调用该实例的getClass()方法获取Class对象
//        Class clazz = person.getClass();
        Class c2 = p.getClass();
        System.out.println(c2.hashCode());
//        已知一个类的全类名,且该类在类路径下,可通过Class类的静态方法forName()获取,有ClassNotFoundException异常
//        Class clazz = Class.forName("demo01.Student");
        try {
            Class c3 = Class.forName("com.classclass.java.Student");
            System.out.println(c3.hashCode());
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
//        内置基本数据类型可以直接用类名.Type
        Class c4 = Integer.TYPE;
        System.out.println(c4);
    }
}
class Person{
    public String name;

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

    public Person() {
    }
}
class Student extends Person{
    public Student() {
        this.name = "学生";
    }
}
class Teacher extends Person{
    public Teacher() {
        this.name = "老师";
    }
}
/*
运行结果:class com.classclass.java.Student
		325040804
		325040804
		325040804
		int
*/
3)哪些类型可以有Class对象

1.class:外部类,成员(成员内部类、静态内部类),局部内部类,匿名内部类
2.interface:接口
3.[ ]:数组
4.enum:枚举
5.annotation:注解@interface
6.primitive type:基本数据类型
7.void

    Class c1 = Object.class;//类
        Class c2 = Comparable.class;//接口
        Class c3 = String[].class;//一维数组
        Class c4 = int[][].class;//二维数组
        Class c5 = ElementType.class;//枚举
        Class c6 = Override.class;//注解
        Class c7 = int.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());
        /*
        运行结果:class java.lang.Object
				interface java.lang.Comparable
				class [Ljava.lang.String;
				class [[I
				class java.lang.annotation.ElementType
				interface java.lang.Override
				int
				void
				class java.lang.Class
				325040804
				325040804
        */
4)Class类的常用方法

1、返回指定类名name的Class对象
static ClassforName(String name)
2、调用缺省构造函数,返回class对象的一个实例
Object newInstance()
3、返回此Class对象所表示的实体(类、接口、数组或void)的名称
getName()
4、返回当前Class对象的父类的Class对象
Class getSuperClass()
5、获取当前Class对象的接口
Class[] getinterfaces()
7、返回一个包含某些Constructor对象的数组
Constructor[] getConstructors()
8、返回一个method对象,此对象的形参类型为paramType
Method getMothed(String name,Class…T)
9、返回Field对象的一个数组
Field[] getDeclaredFields()

3、类的加载与ClassLoader

1)Java内存分析

1.堆:①存放new的对象和数组②可以被所有的线程共享,不会存放别的对象引用
2.栈:①存放基本变量类型(会包含这个基本类型的具体数值)②引用对象的变量(会存放这个引用在堆里面的具体地址)
3.方法区:①可以被所有的线程共享②包含了所有的class和static变量

2)类的加载与ClassLoader

1.加载:将class文件字节码内容加载到内存中,并将这些静态数据转换为方法区的运行时数据结构,然后生成一个代表这个类的java.lang.Class对象
2.链接:将Java类的二进制代码合并到JVM的运行状态之中的过程。
①验证:确保加载的类信息符合JVM规范,没有安全方面的问题
②准备:正式为类变量(static)分配内存并设置类变量默认初始值的阶段,这些内存都将在方法区种进行分配
③解析:虚拟机常量池内的符号引用(常量名)替换为直接引用(地址)的过程
3.初始化:
①执行类构造器< clinit >()方法的过程。类构造器< clinit >()方法是由编译期自动收集类中所有类变量的赋值动作和静态代码块中的语句合并产生的。
②当初始化一个类的时候,如果发现其父类还没有进行初始化,则需要先触发其父类的初始化。
③虚拟机会保证一个类的< clinit >()方法在多线程环境中被正确加锁和同步

public class Test03 {
    public static void main(String[] args) {
        /*
        1.加载到内存,会产生一个类对应Class对象
        2.链接,链接结束后m = 0
        3.初始化
            <clinit>(){
                 System.out.println("A类静态代码块初始化");
                 m = 400;
                 m = 200;
            }
         */
        A a = new A();
        System.out.println(a.m);
    }
}
class A{
    static{
        System.out.println("A类静态代码块初始化");
        m = 400;
    }
    static int m = 200;

    public A(){
        System.out.println("A类的无参构造函数");
    }
}
/*
运行结果:A类静态代码块初始化
		A类的无参构造函数
		200
*/
3)分析类初始化
①类的主动引用(一定发生类的初始化)

1.当虚拟机启动,先初始化main方法所在地类。
2.new一个类的对象
3.调用类的静态成员(除了final常量)和静态方法
4.使用java.lang.reflect包的方法对类进行反射调用

public class Test04 {
    static {
        System.out.println("Main方法被加载");
    }
    public static void main(String[] args) {
        //1、new一个类的对象
        Son son = new Son();
        //2、调用类的静态成员(除了final常量)和静态方法
        System.out.println(new Son().m);
        //3、使用java.lang.reflect包的方法对类进行反射调用
        try {
            Class c1 = Class.forName("com.reflection.java.Son");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}
class Father{
    static{
        System.out.println("父类Father被加载");
    }
    static int b = 1;
}
class Son extends Father{
    static {
        System.out.println("子类Son被加载");
        m = 300;
    }
    static int m = 100;
    static final int M = 2;
}
/*
运行结果分别为:
第一个;
		Main方法被加载
		父类Father被加载
		子类Son被加载
第二个:
		Main方法被加载
		父类Father被加载
		子类Son被加载
第三个:
		Main方法被加载
		父类Father被加载
		子类Son被加载
*/
②类的被动引用(不会发生类的初始化)

1.当访问一个静态域时,只有真正声明这个域的类才会被初始化。如:当通过子类引用父类的静态变量,不会导致子类初始化
2.通过数组定义类引用,不会触发此类的初始化
3.引用常量不会触发此类的初始化(常量在链接阶段就存入调用类的常量池中了)

public class Test04 {
    static {
        System.out.println("Main方法被加载");
    }
    public static void main(String[] args) {
        //1、通过子类引用父类的静态变量
        System.out.println(Son.b);
        //2、数组定义类引用
        Son[] sons = new Son[10];
        //3、引用常量
        System.out.println(Son.M);
    }
}
class Father{
    static{
        System.out.println("父类Father被加载");
    }
    static int b = 1;
}
class Son extends Father{
    static {
        System.out.println("子类Son被加载");
        m = 300;
    }
    static int m = 100;
    static final int M = 2;
}
/*
运行结果:
第一个:
		Main方法被加载
		父类Father被加载
		1
第二个:
		Main方法被加载
第三个:
		Main方法被加载
		2
*/
4)类加载器
①类加载器的作用

1.类加载器的作用:将class文件字节码内容加载到内存中,并将这些静态数据转换成方法区的运行时数据结构,然后在堆中生成一个代表这个类的java.lang.Class对象,作为方法去中类数据的访问入口
2.类缓存:标准的JavaSE类加载器可以按要求查找类,但一旦某个类被加载到类加载器中,它将维持加载(缓存)一段时间。不过JVM垃圾回收机制可以回收这些Class对象
3.加载器的分类:
①引导类加载器:负责Java平台核心库。无法直接获取
②扩展类加载器:负责jre/lib/ext目录下的jar包或-D java.ext.dirs指定目录下的jar包装入工作库
③系统类加载器:负责java-classpaht或 -D java.class.paht所指的目录下的类玉jar包装入工作库,是最常用的加载器。

②常用方法

1、获取系统类的加载器
public static ClassLoader getSystemClassLoader()
2、获取父类加载器
public final ClassLoader getParent()
3、获取当前类的加载器
public ClassLoader getClassLoader()
4、获取系统类加载器可以加载的路径
System.getProperty(“java.class.path”);

public class Test05 {
    public static void main(String[] args) {
        //1、获取系统类的加载器
        ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
        System.out.println(systemClassLoader);
        //2、获取系统类加载器的父类加载器-->扩展类加载器
        ClassLoader parent = systemClassLoader.getParent();
        System.out.println(parent);
        //3、获取扩展类加载器的父类加载器-->根加载器(c/c++)
        ClassLoader grandParent = parent.getParent();
        System.out.println(grandParent);
        //4、测试当前类的加载器
        try {
            ClassLoader classLoader = Class.forName("com.reflection.java.Test05").getClassLoader();
            System.out.println(classLoader);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        //5、测试JDK内置类的加载器
        try {
            ClassLoader classLoader1 = Class.forName("java.lang.Object").getClassLoader();
            System.out.println(classLoader1);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        //6、获取系统类加载器可以加载的路径
        System.out.println(System.getProperty("java.class.path"));
    }
}
/*
运行结果:sun.misc.Launcher$AppClassLoader@18b4aac2
		sun.misc.Launcher$ExtClassLoader@135fbaa4
		null
		sun.misc.Launcher$AppClassLoader@18b4aac2
		null
		D:\java\jdk1.8.0_131\jre\lib\charsets.jar;D:\java\jdk1.8.0_131\jre\lib\deploy.jar;D:\java\jdk1.8.0_131\jre\lib\ext\access-bridge-64.jar;D:\java\jdk1.8.0_131\jre\lib\ext\cldrdata.jar;D:\java\jdk1.8.0_131\jre\lib\ext\dnsns.jar;D:\java\jdk1.8.0_131\jre\lib\ext\jaccess.jar;D:\java\jdk1.8.0_131\jre\lib\ext\jfxrt.jar;D:\java\jdk1.8.0_131\jre\lib\ext\localedata.jar;D:\java\jdk1.8.0_131\jre\lib\ext\nashorn.jar;D:\java\jdk1.8.0_131\jre\lib\ext\sunec.jar;D:\java\jdk1.8.0_131\jre\lib\ext\sunjce_provider.jar;D:\java\jdk1.8.0_131\jre\lib\ext\sunmscapi.jar;D:\java\jdk1.8.0_131\jre\lib\ext\sunpkcs11.jar;D:\java\jdk1.8.0_131\jre\lib\ext\zipfs.jar;D:\java\jdk1.8.0_131\jre\lib\javaws.jar;D:\java\jdk1.8.0_131\jre\lib\jce.jar;D:\java\jdk1.8.0_131\jre\lib\jfr.jar;D:\java\jdk1.8.0_131\jre\lib\jfxswt.jar;D:\java\jdk1.8.0_131\jre\lib\jsse.jar;D:\java\jdk1.8.0_131\jre\lib\management-agent.jar;D:\java\jdk1.8.0_131\jre\lib\plugin.jar;D:\java\jdk1.8.0_131\jre\lib\resources.jar;D:\java\jdk1.8.0_131\jre\lib\rt.jar;D:\AdevelopTools\IdealWorkspace\workspace_TDSoftwareSchoolTeam\out\production\ReflectionDemo;D:\AdevelopTools\java\Ideal\IntelliJ IDEA 2021.1.2\lib\idea_rt.jar

*/

4、获取运行时类的完整结构

1)获取包名、类名

1、获取包名
getPackage().getName()
2、获取类名
getSimpleName()
3.获取完整类名
getName()

        User user = new User();
        Class c1 = user.getClass();

        System.out.println(c1.getPackage().getName());
        System.out.println(c1.getSimpleName());
        System.out.println(c1.getName());
        /*
        运行结果:
        com.reflection.java
		User
		com.reflection.java.User
        */
2)获取成员变量定义信息

1、获取所有公开的成员变量,包括继承变量
getFields()
2、获取本类定义的成员变量,包括私有,但不包括继承的变量
getDeclaredFields()
3、获取指定的公共成员变量
getField(变量名)
4、获取指定的私有成员变量
getDeclaredField(变量名)

        User user = new User();
        Class c1 = user.getClass();
        Field[] fields = c1.getFields();
        for (Field x:
             fields) {
            System.out.println(x);
        }
        System.out.println("*********************");
        Field[] declaredFields = c1.getDeclaredFields();
        for (Field x:
                declaredFields) {
            System.out.println(x);
        }
        System.out.println("***************************");
        Field name = c1.getField("address");
        System.out.println(name);
        System.out.println("**************************");
        Field name1 = c1.getDeclaredField("name");
        System.out.println(name1);
        /*
        运行结果:public java.lang.String com.reflection.java.User.address
				*********************
				private java.lang.String com.reflection.java.User.name
				private int com.reflection.java.User.age
				private int com.reflection.java.User.id
				public java.lang.String com.reflection.java.User.address
				***************************
				public java.lang.String com.reflection.java.User.address
				**************************
				private java.lang.String com.reflection.java.User.name
        */        
3)获取方法定义信息

1、获取所有可见的方法,包括继承的方法
getMethods()
2、获取指定的公有方法
getMethod(方法名,参数类型列表)
3、getDeclaredMethods()
获取本类定义的的方法,包括私有,不包括继承的方法
4、获取指定的私有方法
getDeclaredMethod(方法名,int.class,String.class)

        User user = new User();
        Class c1 = user.getClass();
        Method[] methods = c1.getMethods();
        for (Method x:
             methods) {
            System.out.println(x);
        }
        System.out.println("***********************");
        Field[] declaredFields = c1.getDeclaredFields();
        for (Field x :
                declaredFields) {
            System.out.println(x);
        }
        System.out.println("**************************");
        Method setName = c1.getMethod("setName",String.class);
        Method getName = c1.getMethod("getName", null);
        System.out.println(setName);
        System.out.println(getName);
        System.out.println("***************************");
        Method test = c1.getDeclaredMethod("test", null);
        System.out.println(test);
        /*
        运行结果:public java.lang.String com.reflection.java.User.toString()
				public java.lang.String com.reflection.java.User.getName()
				public int com.reflection.java.User.getId()
				public void com.reflection.java.User.setName(java.lang.String)
				public int com.reflection.java.User.getAge()
				public void com.reflection.java.User.setId(int)
				public void com.reflection.java.User.setAge(int)
				public final void java.lang.Object.wait() throws java.lang.InterruptedException
				public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
				public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
				public boolean java.lang.Object.equals(java.lang.Object)
				public native int java.lang.Object.hashCode()
				public final native java.lang.Class java.lang.Object.getClass()
				public final native void java.lang.Object.notify()
				public final native void java.lang.Object.notifyAll()
				***********************
				private java.lang.String com.reflection.java.User.name
				private int com.reflection.java.User.age
				private int com.reflection.java.User.id
				public java.lang.String com.reflection.java.User.address
				**************************
				public void com.reflection.java.User.setName(java.lang.String)
				public java.lang.String com.reflection.java.User.getName()
				***************************
				private void com.reflection.java.User.test()
        */
4)获取构造方法定义信息

1、获取公开的构造方法
getConstructor(参数类型列表)
2、获取所有的公开的构造方法
getConstructors()
3、获取所有的构造方法,包括私有
getDeclaredConstructors()
4、获取私有构造方法
getDeclaredConstructor(int.class,String.class)

        User user = new User();
        Class c1 = user.getClass();
        Constructor[] constructors = c1.getConstructors();
        for (Constructor x :
                constructors) {
            System.out.println(x);
        }
        System.out.println("************************");
        Constructor[] declaredConstructors = c1.getDeclaredConstructors();
        for (Constructor x :
                declaredConstructors) {
            System.out.println(x);
        }
        System.out.println("****************************");
        Constructor constructor = c1.getConstructor(null);
        System.out.println(constructor);
        System.out.println("*****************************");
        Constructor declaredConstructor = c1.getDeclaredConstructor(String.class, int.class, int.class);
        System.out.println(declaredConstructor);
        /*
        运行结果:public com.reflection.java.User()
				************************
				private com.reflection.java.User(java.lang.String,int,int)
				public com.reflection.java.User()
				****************************
				public com.reflection.java.User()
				*****************************
				private com.reflection.java.User(java.lang.String,int,int)
        */

5、创建运行时类的对象

1)方式一:调用Class对象的newInstance()方法

1、newInstance()
①类必须有一个无参数的构造器
②类的构造器的访问权限需要足够

        Class c1 = Class.forName("com.reflection.java.User");
        User user = (User)c1.newInstance();
        System.out.println(user);
        /*
        运行结果:User{name='null', age=0, id=0}
        */
2)方式二:调用Class对象的getDeclaredConstructor(Class…parameterTypes)方法

1、通过Class类的getDeclaredConstructor(Class…parameterTypes)取得本类的指定形参构造器
2、再调用newInstance(参数…)方法传递一个对象数组进去,里面包含了构造器种所需的各个参数
3、通过Constructor实例化对象

        Class c1 = Class.forName("com.reflection.java.User");
        Constructor constructor = c1.getDeclaredConstructor(String.class, int.class, int.class);
        User user = (User)constructor.newInstance("张三", 20, 2022);
        System.out.println(user);
        /*
        运行结果:User{name='张三', age=20, id=2022}
        */

6、调用运行时类的指定结构

1)调用成员变量

1、获取变量
getDeclaredField(变量名)
2、使私有成员允许访问
setAccessible(true)
3、为指定实例的变量赋值,静态变量,第一参数给null
f.set(实例,值)
4、访问指定实例变量的值,静态变量,第一参数给null
f.get(实例)

        Class c1 = Class.forName("com.reflection.java.User");
        User user = (User)c1.newInstance();
        System.out.println(user.getName());
        Field name = c1.getDeclaredField("name");
        name.setAccessible(true);
        name.set(user,"李四");
        System.out.println(name.get(user));
        /*
        运行结果:null
				李四
        */
2)调用成员方法

1、获取方法
getDeclaredMethod(方法名,参数类型列表)
2、使私有方法允许被调用
m.setAccessible(true)
3、让指定实例来执行该方法
m.invoke(实例,参数数据)

        Class c1 = Class.forName("com.reflection.java.User");
        User user = (User)c1.newInstance();
        Method setName = c1.getDeclaredMethod("setName", String.class);
        setName.invoke(user,"张三");
        System.out.println(user.getName());
        /*
        运行结果:张三
        */

7、反射操作泛型

1、ParameterizedType:表达一种参数化类型,比如 Collection
2、GenericArrayType:表示一种元素类型是参数化类型或者类型变量的数组类型
3、TypeVariable: 是各种类型变量的公共父接口
4、WildcardType: 代表一种通配符类型表达式

   public void test01(Map<String,User> map, List<User> list){
        System.out.println("test01");
    }

    public Map<String,User> test02(){
        System.out.println("test02");
        return null;
    }

    public static void main(String[] args) throws NoSuchMethodException {
        Method method = Test08.class.getMethod("test01", Map.class, List.class);

        Type[] genericParameterTypes = method.getGenericParameterTypes();
        for (Type genericParameterType : genericParameterTypes) {
            System.out.println("###" + genericParameterType);
            if (genericParameterType instanceof ParameterizedType) {
                Type[] actualTypeArguments = ((ParameterizedType) genericParameterType).getActualTypeArguments();
                for (Type typeArgument : actualTypeArguments) {                    
                    System.out.println(typeArgument);
                }
            }
        }
        System.out.println("***********************");
        method = Test08.class.getMethod("test02");
        Type genericReturnType = method.getGenericReturnType();

        if (genericReturnType instanceof ParameterizedType) {
            Type[] actualTypeArguments = ((ParameterizedType) genericReturnType).getActualTypeArguments();
            for (Type typeArgument : actualTypeArguments) {
                
                System.out.println(typeArgument);
            }
        }
    }
    /*
    运行结果:###java.util.Map<java.lang.String, com.reflection.java.User>
			class java.lang.String
			class com.reflection.java.User
			###java.util.List<com.reflection.java.User>
			class com.reflection.java.User
			***********************
			class java.lang.String
			class com.reflection.java.User
    */

8、反射操作注解

  public class Test09 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
        Class c1 = Class.forName("com.reflection.java.Student");
        //通过反射获得注解
        Annotation[] annotations = c1.getAnnotations();
        for (Annotation annotation : annotations) {
            System.out.println(annotation);
        }
        //获得注解的value的值
        TableStudent ts = (TableStudent) c1.getAnnotation(TableStudent.class);
        String value = ts.value();
        System.out.println(value);
        //获得类指定的注解
        Field name = c1.getDeclaredField("name");
        FieldStudent annotation = name.getAnnotation(FieldStudent.class);
        System.out.println(annotation.columName());
        System.out.println(annotation.type());
        System.out.println(annotation.length());
    }
}
@TableStudent("student")
class Student{
    @FieldStudent(columName = "id",type = "int",length = 18)
    private int id;
    @FieldStudent(columName = "age",type = "int",length = 18)
    private int age;
    @FieldStudent(columName = "name",type = "varchar",length = 255)
    private String name;

    public Student() {
    }

    public Student(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;
    }

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

//类名的注解
@TableStudent("student")
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface TableStudent{
    String value();
}
//属性的注解
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface FieldStudent{
    String columName();
    String type();
    int length();
}
        /*
        运行结果:@com.reflection.java.TableStudent(value=student)
				student
				name
				varchar
				255
        */
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值