JAVA——注解、反射

注解(Annotation)

自定义注解

@Target(value = {ElementType.METHOD,ElementType.TYPE})     //设置注解的位置,为方法上面和类接口上面
@Retention(RetentionPolicy.RUNTIME)      //设置注解在运行时
public @interface MyAnnotation {
    int age() default 0;       //设置注解的内容 默认值为0`在这里插入代码片`
    String[] mynames() default {"小周","大周"};
}

使用自定义注解

public class AnnotationTest {
    @MyAnnotation(mynames = {"小二","小小"},age = 18)
    public  void test(){

    }
}

反射(Reflection)

**注意:反射在运行期runtime有效

1. 获取Class对象的三种方式

package com.zzs.Collection;

public class User {

    private String name;
    private int age;

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
    /*有参构造函数*/
    public User(String name,int age){
        this.name = name;
        this.age = age;
    }
    /*无参构造函数*/
    public User(){
        
    }
}

            //获取Class对象的三种方法
            Class clazz1 = Class.forName("com.zzs.Collection.User");
            Class clazz2 = User.class;
            User user = new User();
            Class clazz3 = user.getClass();

2. 同一个类的Class对象只有一个

            //同一个类的Class对象只有一个
            System.out.println(clazz1==clazz2);//true
            System.out.println(clazz1==clazz2);//true

			//获取全路径类名  包名+类名:com.zzs.Collection.User
            System.out.println(clazz1.getName());
            //获得类名称:User
            System.out.println(clazz1.getSimpleName());

3. 获取类的相关信息

a.获取属性的相关信息
			//获取属性信息
            //Field[] fields = clazz1.getFields(); //只能获取public的属性

            Field[] fields = clazz1.getDeclaredFields();//获取所有书信信息
            for (Field field : fields){
                System.out.println("属性"+field);
            }
            /*
            输出:
            属性private java.lang.String com.zzs.Collection.User.name
			属性private int com.zzs.Collection.User.age
            */
            //获取某个指定的属性信息
            Field f = clazz1.getDeclaredField("age");
            System.out.println(f);//private int com.zzs.Collection.User.age
b.获取方法的相关信息
            //获取方法的属性信息
            //有参数是时需要传入参数类型的class,因为重载原因
            Method method = clazz1.getDeclaredMethod("setAge", int.class);
			
			/*返回 Class 对象表示的类或接口的所有已声明的方法数组,但是不包括从父类继承和接口实现的方法。*/
            Method[] methods = clazz1.getDeclaredMethods();
            for (Method m:methods){
                System.out.println("方法"+m);
            }
            /*
			输出
			方法public java.lang.String com.zzs.Collection.User.toString()
			方法public java.lang.String com.zzs.Collection.User.getName()
			方法public void com.zzs.Collection.User.setName(java.lang.String)
			方法public int com.zzs.Collection.User.getAge()
			方法public void com.zzs.Collection.User.setAge(int)
			*/
			
			/*返回当前 Class 对象表示的类或接口的所有公有成员方法对象数组,包括已声明的和从父类继承或实现接口的方法。*/
			Method[] methods2 = clazz1.getMethods();
            for (Method m:methods2){
                System.out.println("方法"+m);
            }
            /*
			输出:
			方法public java.lang.String com.zzs.Collection.User.toString()
			方法public java.lang.String com.zzs.Collection.User.getName()
			方法public void com.zzs.Collection.User.setName(java.lang.String)
			方法public int com.zzs.Collection.User.getAge()
			方法public void com.zzs.Collection.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 java.lang.String java.lang.Object.toString()
			方法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()
			*/

c.获取构造器
			//获得构造器
            Constructor[] constructors = clazz1.getDeclaredConstructors();
            for(Constructor constructor :constructors){
                System.out.println("属性"+constructor);
            }
            /*
			输出:
			构造器public com.zzs.Collection.User()
			构造器public com.zzs.Collection.User(java.lang.String,int)
			*/

4. 通过反射API调用普通方法、操作属性

		
			//通过反射API调用普通方法
			User user2 = (User) clazz1.newInstance();
            Method m = clazz1.getDeclaredMethod("setName", String.class);
            Method m2 = clazz1.getDeclaredMethod("setAge", int.class);
            m.invoke(user2,"zhouzs");//invoke意为调用,传入要执行这个函数的对象和参数
            m2.invoke(user2,18);
            System.out.println(user2);
            /*
			输出:
			User{name='zhouzs', age=18}
			*/
			/*
			注意:通过反射调用方法将使性能下降,调用的时间关系如下:
				普通调用<反射动态调用setAccessible(true)<反射动态调用
				如果一定要反射调用且频繁调用,记得设置setAccessible为true
			*/


			//通过反射API操作属性
            User user3 = (User) clazz1.newInstance();
            Field f1 = clazz1.getDeclaredField("name");
            Field f2 = clazz1.getDeclaredField("age");
            //如果私有属性不调用setAccessible将不能进行set操作,方法也是
            f1.setAccessible(true);//这个属性不需要做安全检查,可以直接访问
            f2.setAccessible(true);
            f1.set(user3,"laozhou");
            f2.set(user3,1);
            System.out.println(user3);
            /*
			输出:
			User{name='laozhou', age=1}
			*/

5. 通过反射API获取泛型

public class MyClass2 {

    /*泛型在参数里*/
    public  void test(Map<String,User> map, List<User> list){
        System.out.println("I'm test");
    }

    /*泛型在返回值里*/
    public  Map<String,User> test2(){
        System.out.println("I'm test2");
        return null;
    }

    public static void main(String[] args) {
        try {
            Method m = Class.forName("com.zzs.Collection.MyClass2").getMethod("test",Map.class,List.class);

            //获取方法的每个带泛型参数
            //即 Map<String,User> map, List<User> list
            Type[] t = m.getGenericParameterTypes();

            for (Type paramType : t){
                System.out.println("****"+paramType);
                if (paramType instanceof ParameterizedType){
                    //获取每个泛型<>里的真正所有类型 比如Mao里的 String 和 User
                    Type[] genericTypes = ((ParameterizedType)paramType).getActualTypeArguments();
                    //遍历泛型<>里的每个类型
                    for (Type genericType :genericTypes){
                        System.out.println("泛型类型"+genericType);
                    }
                }
            }
            
            System.out.println("**********************************");
            
            Method m2 = Class.forName("com.zzs.Collection.MyClass2").getMethod("test2",null);
            /*获取返回的泛型参数*/
            Type returnType = m2.getGenericReturnType();
            if (returnType instanceof ParameterizedType){
                /*获取泛型里的每个参数*/
                Type[] genericTypes = ((ParameterizedType)returnType).getActualTypeArguments();
                for (Type genericType:genericTypes){
                    System.out.println("返回值中的泛型:"+genericType);
                }
            }
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

		输出:
		****java.util.Map<java.lang.String, com.zzs.Collection.User>
		泛型类型class java.lang.String
		泛型类型class com.zzs.Collection.User
		****java.util.List<com.zzs.Collection.User>
		泛型类型class com.zzs.Collection.User
		**********************************
		返回值中的泛型:class java.lang.String
		返回值中的泛型:class com.zzs.Collection.User

6. 通过反射API操作注解

			
			/*测试的自定义注解、注解测试类为顶部注解里的*/
			
			Class clazz = Class.forName("com.zzs.Collection.AnnotationTest");
            /*获取类的所有注解*/
            Annotation[] annotations = clazz.getAnnotations();
            for (Annotation annotation:annotations){
                System.out.println(annotation);
            }

            /*获得类的指定注解*/
            Annotation annotation = clazz.getAnnotation(MyAnnotation.class);
            System.out.println("获得指定注解:"+annotation);

            /*获得类的方法注解*/
            Method method = clazz.getDeclaredMethod("test");
            MyAnnotation annotation1 = method.getAnnotation(MyAnnotation.class);
            System.out.println(annotation1.mynames());//输出的是数组
            System.out.println(annotation1.age());
            /*
			输出:
			@com.zzs.Collection.MyAnnotation(mynames=[类的注解], age=10)
			获得指定注解:@com.zzs.Collection.MyAnnotation(mynames=[类的注解], age=10)
			[Ljava.lang.String;@610455d6
			18
			*/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值