JAVA自学笔记(反射)

本文介绍了Java反射的概念,包括Class、Field、Method和Constructor类的使用。通过反射可以动态创建对象并操作其属性和方法,实现插件开发。同时,讲解了内省机制,利用PropertyDescriptor、BeanInfo和Introspector类实现对属性的访问。文中提供了具体示例代码,展示了如何使用反射设置和获取Student类的name和age属性。
摘要由CSDN通过智能技术生成

什么是类对象

  • 反射:把Java类中的各种组成成分映射成单独的Java对象进行操作

  • 类的对象:基于某个类new出来的对象,也称为实例对象

  • 类对象:类加载的产物,封装了一个类的所有信息(类名、父类、接口、属性、方法、构造方法)

反射相关类

  • Class类:可以获取类和类的成员信息、

  • Field类:可以访问类的属性

  • Method类:可调用类的方法

  • Constructor类:可以调用类的构造方法

package com.fq.day24;
​
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
​
public class ReflectDemo {
    public static void main(String[] args) throws Exception{
        reflect5();
    }
    //反射操作1:获取类对象
    public static void reflect1()throws Exception{
        //h获取类对象的三种方式
        //1.创建类的对象  获取
        Student s1 = new Student("小莲花",12);
        Class class1 = s1.getClass();
        System.out.println(class1.hashCode());
        //第二种方式:通过类名.class获取
        Class class2 = Student.class;
        System.out.println(class2.hashCode());
        //第三方式:通过Class.forName();推荐使用:耦合性低,编译时不依赖目标类
        //Thread.currentThread().getContextClassLoader().getResource("").getPath()
        Class class3 = Class.forName("com.fq.day24.Student");
        System.out.println(class3.hashCode());
    }
​
    //反射操作2:获取类对象信息
    public static void reflect2()throws Exception{
        Class class1 = Class.forName("com.fq.day24.Student");
        System.out.println("类的全名称:"+class1.getName());  //类的全名称:com.fq.day24.Student
        System.out.println("类的简单名称:"+class1.getSimpleName());  //类的简单名称:Student
        System.out.println("类的包名称:"+class1.getPackageName());  //类的包名称:com.fq.day24
        System.out.println("类的父名:"+class1.getSuperclass().getName());  //类的父名:java.lang.Object
        Class[] interfaces = class1.getInterfaces(); //获取类实现的接口
        for (Class inter:interfaces) {
            System.out.println(inter);   //interface java.io.Serializable
        }
    }
​
    //反射操作3:获取类对象的基本信息
    public static void reflect3()throws Exception{
        Class class1 = Class.forName("com.fq.day24.Student");
        //获取所有构造方法
        Constructor[] constructors = class1.getConstructors();
        for (Constructor s:constructors) {
            System.out.println(s);
            //public com.fq.day24.Student(java.lang.String,int)
            //public com.fq.day24.Student()
        }
​
        //获取单个构造方法,默认无参
        Constructor con1 = class1.getConstructor();
        Student s1 = new Student();
        Student s2 = (Student) con1.newInstance();
        System.out.println(s1.toString());  //Student{name='null', age=0}
        System.out.println(s2.toString());  //Student{name='null', age=0}
​
        //获取带参构造方法
        Constructor constructor2 = class1.getConstructor(String.class,int.class);
        Student s3 = (Student) constructor2.newInstance("小莲花",22);
        System.out.println(s3.toString());  //Student{name='小莲花', age=22}
​
        //简写,调用无参构造
        Student s4 = (Student) class1.newInstance();
        System.out.println(s4.toString());  //Student{name='null', age=0}
    }
​
    //反射操作4:获取类对象的普通方法
    public static void reflect4()throws Exception{
        Class class1 = Class.forName("com.fq.day24.Student");
        //获取类的所有的  公开  方法,包括继承的
        Method[] methods = class1.getMethods();
        for (Method m:methods) {
            System.out.println(m);
        }
        //获取类所有的方法,包括非公开的,不包括继承的
        Method[] methods1 = class1.getDeclaredMethods();
        for (Method m:methods) {
            System.out.println(m);
        }
        //获取无参无返回值的方法
        Method methodShow = class1.getMethod("show");
        Student s1 = (Student) class1.newInstance();
        s1.show();   //name:null,age:0
        //反射调用方法
        methodShow.invoke(s1);//=s1.show();  //name:null,age:0
​
        //获取带参方法
        Method method2 = class1.getMethod("show",String.class);
        s1.show("北京");   //学生地址:北京
        method2.invoke(s1,"杭州");   //=s1.show("北京");  //学生地址:杭州
​
        //获取带返回值的方法
        Method getName = class1.getMethod("getName");
        String a = s1.getName();
        System.out.println(a);  //小莲花
        String a1 = (String) getName.invoke(s1);
        System.out.println(a1);  //小莲花
​
        //获取私有方法
        Method study = class1.getDeclaredMethod("study");
        study.setAccessible(true); //将方法的访问修饰符无效
        study.invoke(s1);   //好好学习
​
        //获取静态方法
        Student.exam();  //开始考试
        Method exam = class1.getMethod("exam");
        exam.invoke(null);  // =Student.exam();  //开始考试
    }
​
    //反射操作5:获取类对象的属性
    public static void reflect5() throws Exception{
        Class class1 = Class.forName("com.fq.day24.Student");
        //获取所有的属性
        Field[] fields = class1.getDeclaredFields();
        for (Field f:fields) {
            System.out.println(f);
        }
​
        //获取name属性
        Field name = class1.getDeclaredField("name");
        Student s1 = (Student) class1.newInstance();
        name.setAccessible(true);//访问权限无效
        name.set(s1,"小翠");
        System.out.println(s1.toString());  //Student{name='小翠', age=0}
​
        Field age = class1.getDeclaredField("age");
        age.setAccessible(true);//访问权限无效
        age.set(s1,23);
        System.out.println(s1.toString());  //Student{name='小翠', age=23}
​
    }
}

反射的优点和缺点

  • 优点

    • 提高了JAVA程序的灵活性和扩展性,降低了耦合性,提高自适应能力

    • 允许程旭创建和控制任何类的对象,无需提前硬编码目标类

  • 缺点

    • 性能问题

    • 代码维护问题

使用反射实现插件开发

package com.fq.day24;
​
public interface CarService {
    void run();
    void turn(String dic);
}
package com.fq.day24;
​
public class BaoMa implements CarService{
    @Override
    public void run() {
        System.out.println("宝马开始奔跑。。。。");
    }
​
    @Override
    public void turn(String dic) {
        System.out.println("宝马向"+dic+"转向");
    }
}
package com.fq.day24;
​
public class BenChi implements CarService{
    @Override
    public void run() {
        System.out.println("奔驰开始奔跑。。。。");
    }
​
    @Override
    public void turn(String dic) {
        System.out.println("奔驰向"+dic+"转向");
    }
}
package com.fq.day24;
​
import java.io.BufferedReader;
import java.io.FileReader;
​
public class TestCarService {
    public static void main(String[] args) throws Exception{
        FileReader fr = new FileReader("F:\\workspace\\Java-Idea-workspace\\JavaGP8QF\\Day24(0619)\\car.txt");
        BufferedReader br = new BufferedReader(fr);
        String classname;
        while ((classname=br.readLine())!=null){
            try{
                System.out.println(classname);
                Class class1 = Class.forName(classname);
                CarService carService = (CarService)class1.newInstance();
                carService.run();
                carService.turn("北");
            }catch (Exception e){
                continue;
            }
        }
    }
}

内省

  • 内省:才用反射机制实现对属性进行操作的一种机制

    • PropertyDescriptor:属性描述符,代表一个属性

    • BeanInfo:实体类信息,包含类的信息

    • Introspector:工具类

  • package com.fq.day24;
    ​
    import java.io.Serializable;
    ​
    public class Student implements Serializable {
        private String name;
        private int age;
        public Student(){
    ​
        }
    ​
        public void setName(String name) {
            this.name = name;
        }
    ​
        public int getAge() {
            return age;
        }
    ​
        public void setAge(int age) {
            this.age = age;
        }
    ​
        public Student(String name, int age) {
            this.name = name;
            this.age = age;
        }
        public void show(){
            System.out.println("name:"+name+",age:"+age);
        }
        public  void show(String address){
            System.out.println("学生地址:"+address);
        }
    ​
        public String getName(){
            return "小莲花";
        }
        private  void study(){
            System.out.println("好好学习");
        }
        public static void exam(){
            System.out.println("开始考试");
        }
    ​
        @Override
        public String toString() {
            return "Student{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    '}';
        }
    }
  • package com.fq.day24;
    ​
    import java.beans.BeanInfo;
    import java.beans.Introspector;
    import java.beans.PropertyDescriptor;
    import java.lang.reflect.Method;
    ​
    public class TestStudent {
        public static void main(String[] args) throws Exception{
            Class<?> class1 = Class.forName("com.fq.day24.Student");
            Student s1 = (Student) class1.newInstance();
    ​
            PropertyDescriptor pd = new PropertyDescriptor("name",class1);
            Method setName = pd.getWriteMethod();
            Object name = "小莲花";
            setName.invoke(s1,name);
    ​
            PropertyDescriptor pd1 = new PropertyDescriptor("age",class1);
            Method setAge = pd1.getWriteMethod();
            Object age = 20;
            setAge.invoke(s1,age);
    ​
            System.out.println(s1.toString());   //Student{name='小莲花', age=20}
    ​
            System.out.println("_--------------------------_");
            //如果类中有getXXX(无参有返回值)、setXXX(有参无返回值)、isXXX(无参有返回值,类型是boolean),认为类中有这种属性
            //获取类的信息
            BeanInfo beanInfo = Introspector.getBeanInfo(class1);
            //获取属性
            PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors();
            for (PropertyDescriptor p:pds) {
                System.out.println(p.getName());
                //age
                //class
               // name
            }
        }
    }
    

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值