反射与注解

什么是反射?
 


    Java中的反射是指在程序运行的时候,通过Class对象拿到类中构造方法,成员方法,成员变量,并且操作构造方法,成员方法,成员变量

反射的应用场景?
        1.各种IDE(集成开发工具)
        2.各种框架

    反射的好处:
        1.可以在程序运行过程中,操作这些对象。
        2.可以解耦,提高程序的可扩展性。

        3.灵活,修改文件,不需要修改代码(降低代码的耦合性)
        4.后面写的文件可以直接加进来使用(提高程序的扩展性)

小结
    1.什么是反射?
        Java中的反射是指在程序运行的时候,通过Class对象拿到类中构造方法,成员方法,成员变量,并且操作构造方法,成员方法,成员变量

三种获取Class对象的方式
    1.类名.class
    2.对象.getClass()
    3.Class.forName(类全名);

 1 ,// 1.类名.class
Class cls1 = Employee.class;
System.out.println(cls1);            // class com.itheima.bean.Employee

2,

Employee e = new Employee();
Class cls2 = e.getClass();
System.out.println(cls2); // class com.itheima.bean.Employee

3

Class cls3 = Class.forName("com.itheima.bean.Employee");
System.out.println(cls3); // class com.itheima.bean.Employee      最常用的就是这种
Class类中的方法:
    getName: 获取类全名 com.itheima.bean.Employee
    getSimpleName: 获取类名 Employee
Class cls = Class.forName("com.itheima.bean.Employee");
System.out.println(cls.getName()); // com.itheima.bean.Employee
System.out.println(cls.getSimpleName()); // Employee

Constructor类作用:
 

 Constructor表示类中的构造方法,必须先获得Class对象  ,然后就通过Class对象,可以指定取哪一个构造器的方法,不管权限

Constructors             必须先获得Class对象  ,然后就通过Class对象 可以获取所有的构造器的方法

Class cls = Class.forName("com.itheima.bean.Employee");

Constructor c1 = cls.getConstructor();

Object o =  c1.newInstance("凤凰街",18);   //创建实例 / 对象

 

如何得到声明的Constructor?
    getDeclaredConstructors: 获取所有声明的Constructor,全部的方法,包括构造方法
    getDeclaredConstructor: 获取一个声明的Constructor,获取随意一个方法,包括构造方法

Class cla=Class.forName("com.itheima.bean.Employee");
Constructor c1 = cla.getDeclaredConstructor(String.class);
c1.setAccessible(true);    //暴力反射
Employee o = (Employee) c1.newInstance("我爱你");     //创建实例

System.out.println(o);

------------------------------------------------------

Class cls = Class.forName("com.itheima.bean.Employee");
Employee e1 = (Employee) cls.newInstance(); // 调用Employee类的无参构造创建对象,只能创建无参构造器

Constructor c2 = cls.getConstructor();
Employee e2 = (Employee) c2.newInstance(); // 调用Employee类的无参构造创建对象或有参构造创建对象

Employee e3 = new Employee();

 

getMethods: 获取所有的public的方法(包括父类的)
getMethod: 获取一个的public的方法
getDeclaredMethods: 获取所有声明的方法(只包含本类)
getDeclaredMethod: 获取一个声明的方法

 

invoke(Object obj, Object ... objs)

  // 1.获取Class对象
        Class cls = Class.forName("com.itheima.bean.Employee");
        Employee e1 = (Employee) cls.newInstance();
        // 2.通过Class对象获取Method
        // getMethods: 获取所有的public的方法(包括父类的)
//        Method[] methods = cls.getMethods();
//        for (Method m : methods) {
//            System.out.println(m);
//        }

        // getMethod: 获取一个的public的方法
        Method m1 = cls.getMethod("setName", String.class);
        System.out.println(m1);
        // 对象.方法名(); 使用对象调用方
        // 使用e1对象调用m1(setName)方法,传入的参数是"苍老师".
        m1.invoke(e1, "苍老师");
        System.out.println(e1); // Employee{name='苍老师', age=0}

        // getDeclaredMethods: 获取所有声明的方法(只包含本类)
//        Method[] methods = cls.getDeclaredMethods();
//        for (Method m : methods) {
//            System.out.println(m);
//        }
        // getDeclaredMethod: 获取一个声明的方法
        Method m2 = cls.getDeclaredMethod("sleep", int.class);
        System.out.println(m2);
        m2.setAccessible(true);
        Object re = m2.invoke(e1, 10);
        System.out.println("返回值: " + re);

 

 

Field的操作:
    赋值,取值
    引用数据类型:
        get();
        set();

    基本数据类型:
        getXxx();   getDouble(),getInt()
        setXxx();   setDouble(),setInt()

getFields: 获取所有public的成员变量
getField: 获取一个publicd的成员变量
getDeclaredFields: 获取所有声明的成员变量
getDeclaredField: 获取一个声明的成员变量

 

                                              注解:

注释:对程序进行解释说明的文字。注释给程序员看的

什么是注解?
    给程序使用的,注解可以给类携带额外的信息

常见注解:
    1.@author:用来标识作者名。
    2.@version:用于标识对象的版本号。
    3.@since: 从哪个版本开始
    4.@Override :检测是否是重写方法

注解的作用:
    编写文档:通过代码里标识的注解生成文档【生成文档doc文档】
    编译检查:通过代码里标识的注解让编译器能够实现基本的编译检查【Override】
    代码分析:通过代码里标识的注解对代码进行分析【使用反射】
自定义注解的格式?                                        注解的属性类型:
                                                     1.八种基本数据类型
 注意:自定义的类型不行                                2.String,枚举,注解可以
                                                3.以上类型的一维数组[]
@interface { 
// 属性 数据类型 属性名(); 
}
    

使用自定义注解格式:
    @注解名(属性名1=属性值1, 属性名2=属性值2,...)

注意:需要保证注解的每个属性都有值.
public @interface MyAnno2 {
    // 属性
    String[] authors(); // 作者
    double price() default 0.99; // 价格
    String name(); // 书名
}





@MyAnno2(name="西游记", price=9.9, authors={"吴承恩", "丘处机", "李天一"})
public class Demo102 {

    @MyAnno2(name = "东游记", authors = {"黄思洁"})
    public static void main(String[] args) {

    }
}

当注解中只有一个属性,并且属性名是value,在使用注解时,可以省略属性名

两种写法

@MyAnno3(value = "aaa")     第一种
public class Demo11 {
    @MyAnno3("aaa")           第二种
    public static void main(String[] args) {

    }
}
1.什么是元注解?
    修饰注解的注解

2.@Target元注解
    @Target:限制注解能放在什么地方(默认是任何地方都能放)

3.@Retention元注解
    限制注解能活到什么时候 (默认是CLASS阶段)
    SOURCE          CLASS       RUNTIME
    源代码阶段
    .java       ->  .class   -> 运行
//@Target(ElementType.TYPE) // 能放在类或者接口上
//@Target(ElementType.CONSTRUCTOR) // 能放在构造方法上
//@Target(ElementType.FIELD) // 能放在成员变量上
//@Target(ElementType.METHOD) // 能放在方法上
//@Target(ElementType.LOCAL_VARIABLE) // 能放在局部变量上
//@Target({ElementType.TYPE, ElementType.CONSTRUCTOR}) // 能放在局部变量上

//@Retention(RetentionPolicy.SOURCE) // 能存活到源代码阶段
//@Retention(RetentionPolicy.CLASS) // 能存活到class阶段
@Retention(RetentionPolicy.RUNTIME) // 能存活到运行时阶段

 

public class Book {
    @MyAnno4
    @BookAnno(name = "西游记", price = 99, authors = {"吴承恩", "丘处机", "李春芳"})
    public void sale(String name, double price, String[] authors) {

    }
}
public class Demo13 {
    // 我们点左边绿色的三角形,程序就运行起来的.
    public static void main(String[] args) throws Exception {
        // 1.获取Class对象
        Class cls = Class.forName("com.itheima.demo13注解解析.Book");

        // 2.获取Method
        Method method = cls.getMethod("sale",String.class,double.class,String[].class);

        // 3.通过Method获取注解
//        Annotation[] annotations = method.getAnnotations();
//        for (Annotation a : annotations) {
//            System.out.println(a);
//        }

        // 在获取一个注解的时候最好先判断方法上是否有这个注解
        boolean b = method.isAnnotationPresent(BookAnno.class);
        System.out.println(b);
        if (b) {
            BookAnno an = method.getAnnotation(BookAnno.class);
            System.out.println(an.name() + " :: " + an.price() + " :: " + Arrays.toString(an.authors()));
        }
    }
}

通过反射可以拿到所对应的值

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值