JAVA注解和反射

一:注解

1.注解格式:@“注解名“
2.内置注解:@Override,@Deprecated,@SuppressWarnings
3.元注解: @Target,@Retention(RUNTIME>CLASS>SOURCE),@Document,@Inherited
4.自定义注解:a.@interface自动继承了Annotation接口了
             b.注解参数:参数类型+参数名()
package annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
public class Main {
    @MyAnnatation01(name="张三")
    public void func01(){
        System.out.println();
    }
    @MyAnnatation02("张三")
    public void func02(){
        System.out.println();
    }
    @MyAnnatation03(age=22)
    public void func03(){
        System.out.println();
    }
}
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnatation01{
    //注解参数:参数类型+参数名()
    String name();
}
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnatation02{
    String value();     //可用默认
}
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnatation03{
    String name() default "";
    int id()default -1;
    int[] score()default {85,75,60};
    int age();
}

二:反射

1.反射概述:

 1.java是静态语言,通过反射变为了准动态语言
 2.反射很强大,可以通过Refletion API任何类的内部信息,并能操作任意对象的内部属性及方法
 3.四种获取Class对象方式(类名):
                      (1. forname(“包名下的路径”)
                      (2. 对象名.getClass()
                      (3. 类名.class
                      (4. 基本类型包装类.Type
 5.一种获取其父类的Class对象方式: 对象名.getSuperClass()
 6.类被加载后,其该类的整体结构被封装到Class对象中,在内存中,一个类只有一个Class对象
package reflection;
import java.lang.annotation.ElementType;
public class Main {

    public static void main(String[] args) throws ClassNotFoundException {
        Person user = new Person();
        //1.通过forName("")获取
        Class c1 = Class.forName("reflection.Person");
        Class c2 = Class.forName("reflection.Person");
        System.out.println("c2 = " + c2);
        //2.通过对象获取
        Man man = new Man();
        Class c3 = man.getClass();
        System.out.println("c3 = " + c3);
        //3.通过类名获取
        Class c4 = Person.class;
        System.out.println("c4 = " + c4);
        Class c5 = Man.class;
        System.out.println("c5 = " + c5);
        Class c6 = Main.class;
        System.out.println("c6 = " + c6);
        //4.通过基本类型包装类的Type属性
        Class c7 = Integer.TYPE;
        System.out.println("c7 = " + c7);
        //5.获取父类的Class名
        System.out.println("c8 = " + c3.getSuperclass());
        //6.类被加载后,其该类的整体结构被封装到Class对象中,在内存中,一个类只有一个Class对象
        System.out.println(c1.hashCode());
        System.out.println(c2.hashCode());
        System.out.println(c6.hashCode());
        System.out.println("-------------");
        showAllClass();
    }
    //7.大部分类型的Class对象
    public static void showAllClass(){
        Class c1 = Object.class;
        Class c2 = Comparable.class;
        Class c3 = int[].class;
        Class c4 = int[][].class;
        Class c5 = Override.class;
        Class c6 = ElementType.class;
        Class c7 = Integer.class;
        Class c8 = Void.class;
        Class c9 = 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);
        System.out.println("-----------");
        //同类型的数组其Class对象与数组的长度无光
        int[] a1 =new int[10];
        int[] a2=new int[100];
        System.out.println(a1.getClass());
        System.out.println(a2.getClass());
    }
}

class Person {
    String name;
    int age;
    public int id;

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

    public Person() {

    }

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

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    public int getId() {
        return id;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public void setId(int id) {
        this.id = id;
    }
    private void test(){}
}
class Man extends Person{
}

2.初识类加载内存机制:

1.类加载:将Class字节码文件加载到内存中,对应生成唯一的Class对象(方法区——>堆)
2.链接:为所有类变量(static)分配内存并为其设置默认初始值(方法区)
3.初始化:<clinit>()将所有赋值动作和静态代码块合并(栈)
package reflection;
public class ClassLoading01 {
    static{
        System.out.println("Main被加载");
    }
    public static void main(String[] args) throws ClassNotFoundException {
        ClassMemory();    //类加载内存机制

        //1.通过new来主动引用
        Son son=new Son();
        //2.通过forName()来主动引用
        //Class aClass = Class.forName("reflection.Son");

        //1.子类调用父类的静态方法不会触发自身类的主动引用
        //System.out.println(Son.mFather);
        //2.创建数组不会触发主动引用
        //Son[] vsSon=new Son[10];
    }

    //类内存加载机制
    public static void ClassMemory(){
        A a=new A();        //new操作在堆区
        System.out.println(a.m);
    }
}

//测试类加载的内存机制
class A{
    static{
        System.out.println("静态代码块初始化");
        m=300;
    }
    public static int m=100;
    A(){
        System.out.println("A的构造函数调用");
    }
}

class Father{
    static {
        System.out.println("父类被加载");
    }
    public static int mFather=1;
}

class Son extends Father{
    static {
        System.out.println("子类被加载");
    }
    public static int mSon=1;
    public static final int nFinalSon=2;
}

3.初识类加载器:

一.类加载器:
   1.系统类加载器:ClassLoader.getSystemClassLoader()
   2.扩展类加载器:systemClassLoader.getParent()
   3.引导类(根)加载器(C/C++编写):扩展类加载器.getParent()
   4.测试当前类和内置类的加载器
   5.获取系统加载器可以加载的路径:同4获取class对象.getClassLoader()
   6.双亲委派机制
二.获取类运行时结构:
   1.获取类名(全包名,只类名):Class对象.getName()
   2.获取属性值(公有,所有,指定):
           公有: Class对象.getFields()
           所有:Class对象.getDeclaredFields()
           指定:对应方法去掉s+属性名参数
   3.获取方法(公有,所有,指定):
           公有:Class对象.getMethods()
           所有:Class对象.getDeclaredMethods()
           指定:对应方法去掉s+函数名参数
   4.获取构造方法(公有,指定)
           公有:Class对象.getConstructors()
           指定:对应函数去掉s+实际参数的class
三:反射动态创建对象并执行方法:
   1.无参创建对象和有参创建:
           无参:Class对象.newInstance()
           有参:Class对象..getConstructor(实际参数的Class对象)
   2.获取方法并调用:
           获取:Class对象.getMethod("方法名", 参数的Class对象)
           调用:方法名.invoke(创建的对象名, 参数)
   3.操作属性并调用
        权限检测:创建的对象名.setAccessible(true),ture为关闭
           调用:获取属性名后.set(创建的对象名,参数)
四:对象调用性能对比分析:
   1.普通对象调用(约3ms)
   2.通过反射调用(约3592ms)
   3.通过反射调用并关掉安全性权限检测(约1847ms)
   4.若频繁调用反射,可关闭安全检测提升性能
package reflection;

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

public class ClassLoading02 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        //一:类加载器
        classLoadTest();
        //二:获取类运行时结构
        getClassRuning();
        //三:反射动态创建对象并执行
        createClassRuning();
        //四:对象调用性能分析
        performanceAnalyze();
    }

    //一:类加载器
    public static void classLoadTest() throws ClassNotFoundException {
        //获取系统加载器
        ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
        System.out.println(systemClassLoader);
        //获取扩展类加载器
        ClassLoader parent1 = systemClassLoader.getParent();
        System.out.println(parent1);
        //获取根加载器(无法直接获取)
        ClassLoader parent2 = parent1.getParent();
        System.out.println(parent2);
        //获取当前类的加载器
        Class<?> aClass = Class.forName("reflection.ClassLoading02");
        System.out.println(aClass.getClassLoader());
        //获取内置类的加载器:Object类的加载器是根加载器
        ClassLoader classLoader = Class.forName("java.lang.Object").getClassLoader();
        System.out.println(classLoader);
        //获取系统加载器可加载的路径
        System.out.println(System.getProperty("java.class.path"));
    }

    //二:获取类运行时结构
    public static void getClassRuning() throws NoSuchFieldException, NoSuchMethodException {
        System.out.println("----------------");
        Person person = new Person();
        Class<? extends Person> aClass = person.getClass();
        //1.获取类名
        String name = aClass.getName();
        String simpleName = aClass.getSimpleName();
        System.out.println("全名:" + name);
        System.out.println("类名" + simpleName);
        System.out.println("----------------");
        //2.获取属性值
        Field[] declaredFields = aClass.getDeclaredFields();
        Field[] fields = aClass.getFields();
        Field field = aClass.getDeclaredField("name");
        Field id = aClass.getField("id");
        for (Field declaredField : declaredFields) {
            System.out.println("所有属性:"+declaredField);
        }
        for (Field field1 : fields) {
            System.out.println("公有属性:"+field);
        }
        System.out.println("指定私有属性:" + field);
        System.out.println("指定共有属性:"+id);
        System.out.println("----------------------");
        //3.获取方法
        Method[] methods = aClass.getMethods();
        Method[] declaredMethods = aClass.getDeclaredMethods();
        Method getId = aClass.getMethod("setId", int.class);//重载,第二个参数是方法的参数类型
        Method test = aClass.getDeclaredMethod("test", null);
        for (Method method : methods) {
            System.out.println("共有方法:"+method);
        }
        for (Method declaredMethod : declaredMethods) {
            System.out.println("所有方法:"+declaredMethod);
        }
        System.out.println("指定共有方法:" + getId);
        System.out.println("指定私有方法:"+test);
        System.out.println("-------------------");
        //4.获取构造器
        Constructor<?>[] constructors = aClass.getConstructors();
        for (Constructor<?> constructor : constructors) {
            System.out.println("获取构造器:"+constructor);
        }
        Constructor<? extends Person> constructor = aClass.getConstructor(String.class, int.class, int.class);
        System.out.println("获取指定构造器:"+constructor);
    }

    //三:反射动态创建对象并执行
    public static void createClassRuning() throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
        System.out.println("###################");
        Class<?> aClass = Class.forName("reflection.Person");
        //1.获取无参对象
        Object o = aClass.newInstance();
        System.out.println("反射创建无参对象:"+o);
        //2.获取有参对象
        Constructor<?> constructor = aClass.getConstructor(String.class, int.class, int.class);
        Object person = constructor.newInstance("张三", 22, 101);
        System.out.println("反射创建有参对象:"+person);
        //3.获取方法
        Method setName = aClass.getMethod("setName", String.class);
        setName.invoke(person, "李四");//invoke激活函数
        System.out.println("反射调用函数:"+person);
        //4.操作属性
        Field personName = aClass.getDeclaredField("name");
        //关闭安全权限检测
        personName.setAccessible(true);
        personName.set(person,"王五");
        System.out.println("反射操作属性:name:"+personName.get(person));
    }

    //四:对象调用性能分析
    public static void performanceAnalyze() throws ClassNotFoundException, InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException {
        System.out.println();
        System.out.println("---------------------");
        test01();//3ms
        test02();//3592ms
        test03();//1847ms
    }
    public static void test01(){
        Person person=new Person("zhangsan",18,28);
        long startTime = System.currentTimeMillis();
        for (int i = 0; i < 1000000000; i++) {
            person.getName();
        }
        long endTime = System.currentTimeMillis();
        System.out.println("普通对象调用:"+(endTime-startTime)+"ms");
    }
    public static void test02() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        Class aClass = Class.forName("reflection.Person");
        Constructor constructor = aClass.getConstructor(String.class, int.class, int.class);
        Object person = constructor.newInstance("zhangsan", 18, 28);
        Method getName = aClass.getMethod("getName", null);
        long startTime = System.currentTimeMillis();
        for (int i = 0; i < 1000000000; i++) {
            getName.invoke(person,null);
        }
        long endTime = System.currentTimeMillis();
        System.out.println("通过反射调用:"+(endTime-startTime)+"ms");
    }
    public static void test03() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        Class aClass = Class.forName("reflection.Person");
        Constructor constructor = aClass.getConstructor(String.class, int.class, int.class);
        Object person = constructor.newInstance("zhangsan", 18, 28);
        Method getName = aClass.getMethod("getName", null);
        getName.setAccessible(true);
        long startTime = System.currentTimeMillis();
        for (int i = 0; i < 1000000000; i++) {
            getName.invoke(person,null);
        }
        long endTime = System.currentTimeMillis();
        System.out.println("通过反射并关闭安全检测调用:"+(endTime-startTime)+"ms");
    }
}

4.反射获取泛型信息:

1.获取函数的泛型参数类型:
        泛型参数类型:方法名.getGenericParameterTypes()
        判断泛型参数为参数化类型:if(genericParameterType instanceof ParameterizedType)
        强转为参数化类型:((ParameterizedType) genericParameterType).getActualTypeArguments()
2.获取函数的返回泛型类型:
        返回泛型类型:方法名.getGenericReturnType()
        判断泛型参数为参数化类型:同上
        强转为参数化类型:同上
在这里插入代码片package reflection;

import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Map;

public class GetGenericityInformantion {
    public void test01(Map<String,Person> arg){

    }
    public Map<String,Person> test02(){
        return null;
    }

    public static void main(String[] args) throws NoSuchMethodException {
        //1.获取函数的泛型参数类型
        Method test01 = GetGenericityInformantion.class.getMethod("test01", Map.class);
            //获取方法的泛型参数类型
        Type[] genericParameterTypes = test01.getGenericParameterTypes();
        for (Type genericParameterType : genericParameterTypes) {
            //打印泛型参数类型
            System.out.println("函数参数类型:"+genericParameterType);
            //如果该泛型参数为参数化类型
            if (genericParameterType instanceof ParameterizedType){
            //将该泛型参数强转为参数化类型再获取实际的类型参数
                Type[] actualTypeArguments = ((ParameterizedType) genericParameterType).getActualTypeArguments();
                for (Type actualTypeArgument : actualTypeArguments) {
                    System.out.println("实际的类型参数:"+actualTypeArgument);
                }
            }
        }
        System.out.println("-------------------");
        //2.获取函数的返回泛型类型
        Method test02 = GetGenericityInformantion.class.getMethod("test02");
        Type genericReturnType = test02.getGenericReturnType();
        System.out.println("函数返回的泛型类型:"+genericReturnType);
        if (genericReturnType instanceof ParameterizedType){
            Type[] actualTypeArguments = ((ParameterizedType) genericReturnType).getActualTypeArguments();
            for (Type actualTypeArgument : actualTypeArguments) {
                System.out.println("函数返回的泛型信息:"+actualTypeArgument);
            }
        }
    }
}

5.反射调用注解:

1.反射调用类的注解的value
2.反射调用类属性的注解value
package reflection;

import com.sun.jdi.Value;

import java.lang.annotation.*;
import java.lang.reflect.Field;

public class ReflectionCallAnnotation {
    public static void main(String[] args) throws ClassNotFoundException {
        //1.获取类的注解信息
        Class<?> c1 = Class.forName("reflection.Student");
        Annotation[] annotations = c1.getAnnotations();//直接通过Class对象获取注解
        for (Annotation annotation : annotations) {
            System.out.println("获取类注解信息:"+annotation);
        }

        //2.获取类注解的value()
        ClassAnnotation annotation = (ClassAnnotation)c1.getAnnotation(ClassAnnotation.class);
        System.out.println("获取类注解的value():"+annotation.value());//传递注解class参数获取

        //2.获取类属性的注解信息
        Field[] declaredFields = c1.getDeclaredFields();
        for (Field declaredField : declaredFields) {//传递注解class参数获取
            FieldAnnotation annotation1 = declaredField.getAnnotation(FieldAnnotation.class);
            System.out.println("获取类属性的直接信息:"+"<"+declaredField.getName()+">"+annotation1.name()+" "+annotation1.type()+" "+annotation1.length());
        }
    }
}
@ClassAnnotation("db_student")
class Student{
    @FieldAnnotation(name="sName",type ="varchar",length = 5)
    private String sName;
    @FieldAnnotation(name="nIage",type = "int",length = 6)
    private int nIge;
    @FieldAnnotation(name = "sId",type = "varchar",length = 12)
    private String sId;

    public Student() {
    }

    public Student(String sName, int nIge, String sId) {
        this.sName = sName;
        this.nIge = nIge;
        this.sId = sId;
    }

    @Override
    public String toString() {
        return "Student{" +
                "sName='" + sName + '\'' +
                ", nIge=" + nIge +
                ", sId='" + sId + '\'' +
                '}';
    }

    public void setsName(String sName) {
        this.sName = sName;
    }

    public void setnIge(int nIge) {
        this.nIge = nIge;
    }

    public void setsId(String sId) {
        this.sId = sId;
    }

    public String getsName() {
        return sName;
    }

    public int getnIge() {
        return nIge;
    }

    public String getsId() {
        return sId;
    }
}
//对类的注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface ClassAnnotation{
    String value();
}
//对属性的注解
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface FieldAnnotation{
    String name();
    String type();
    int length();
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不羁的风zk

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值