java--反射

反射的认识

反射:就是 加载类(),并允许以编程的方式,解剖类中的各种成分(成员变量、成员方法、构造器等)

有什么作用?

获取类的信息、操作他们

反射具体怎么用?

获取Class对象的三种方法:

public class Main {
    public static void main(String[] args) throws ClassNotFoundException {
        //类名.class
        Class c1 = Objecter.class;
        System.out.println(c1);//全类名 = 包名 + 类名
        System.out.println(c1.getSimpleName());//简单的就是类名
​
        //Class的静态方法forName()
        Class c2 = Class.forName("com.yym.test.Objecter");
        System.out.println(c2);
        System.out.println(c1 == c2);//比较地址
​
        //实例对象.getClass()
        Objecter objecter = new Objecter();
        Class c3 = objecter.getClass();
        System.out.println(c3);
        System.out.println(c3 == c2);
    }
}

获取类的构造器并对其进行操作:

import java.lang.reflect.Constructor;
​
public class Main {
    //获取Objecter的全部构造器
    public static void main(String[] args) throws Exception {
        //1. 反射第一步:必须先得到这个类的Class对象
        Class c = Objecter.class;
        
        //2. 获取类的全部构造器
//        Constructor[] constructors = c.getConstructors();//只能获取public的构造器
        Constructor[] constructors = c.getDeclaredConstructors();//获取全部权限的构造器
        
        //3. 遍历数组中每个构造器对象
        for (Constructor constructor : constructors) {
            //构造器名称 + 构造器参数个数
            System.out.println(constructor.getName() + "---->" + constructor.getParameterCount());
            //构造器名称 + 构造器参数类型(后面的方法返回的是类型的数组,因此用Arrays.toString,Arrays中的toString方法已经被重写了)
//            System.out.println(constructor.getName() + "---->" + Arrays.toString(constructor.getParameterTypes()));
        }
        
        //4. 获取无参构造器
        //Constructor constructor = c.getConstructor();//只能获取public修饰的无参构造器
        Constructor constructor = c.getDeclaredConstructor();//获取全部权限的构造器
        System.out.println(constructor.getName() + "----->" + constructor.getParameterCount());
        
        //5. 获取有参构造器(这里的参数:.class代表类型【相当于一种变量】,如果只有类型,那么参数列表的结构不对了【类型 变量】)
        Constructor constructor1 = c.getDeclaredConstructor(int.class,String.class);
        System.out.println(constructor1.getName() + "----->" + constructor1.getParameterCount());
​
​
    }
}

获取类构造器的作用(初始化对象返回):

//类
public class Objecter {
    private int age;
    private String name;
​
    public Objecter(int age, String name) {
        this.age = age;
        this.name = name;
        System.out.println("有参构造器启动!!!");
    }
​
    public Objecter() {
        System.out.println("无参构造器启动!!!");
    }
​
    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 "Objecter{" +
                "age=" + age +
                ", name='" + name + '\'' +
                '}';
    }
}
​
//Test
import java.lang.reflect.Constructor;
​
public class Main {
    //获取Objecter的全部构造器
    public static void main(String[] args) throws Exception {
        //1. 反射第一步:必须先得到这个类的Class对象
        Class c = Objecter.class;
​
        //2. 获取无参构造器
        Constructor constructor = c.getDeclaredConstructor();//获取全部权限的构造器
        //3. 获取无参构造器怎么初始化并返回对象?
        Objecter object1 = (Objecter)constructor.newInstance();
        System.out.println(object1);
​
        //4. 获取有参构造器(这里的参数:.class代表类型【相当于一种变量】,如果只有类型,那么参数列表的结构不对了【类型 变量】)
        Constructor constructor1 = c.getDeclaredConstructor(int.class,String.class);
        //5. 获取有参构造器并返回对象
        Objecter object2 = (Objecter) constructor1.newInstance(9,"hello");
        System.out.println(object2);
    }
}

注意:

看下面的图,这里有个 setAccessible()方法,设置为true后,就算构造器为private修饰也可以访问,破环了类的封装性

 

获取到类的成员变量、对成员变量操作(赋值、取值)

 

获取到类的成员方法

 

(作用:执行)

反射的作用、应用场景(简单了解)

基本作用:

可以得到一个类的全部成分然后操作

可以破环封装性

适合做框架,基本主流框架都会基于反射设计一些通用的功能

### 使用反射做一个简易版的框架

需求:

实现步骤:

1. 定义一个方法,可以接收任意对象。
2. 每收到一个对象后,使用反射获取该对象的Class对象,然后获取全部的成员变量
3. 遍历成员变量,然后提取成员变量在该对象中的具体值
4. 把成员变量名、该变量的值、写出到文件中去;

```java
package TestFrame;

public class Student {
    private String name;
    private int age;
    private char sex;
    private double height;
    private String hobby;

    public Student() {
    }

    public Student(String name, int age, char sex, double height, String hobby) {
        this.name = name;
        this.age = age;
        this.sex = sex;
        this.height = height;
        this.hobby = hobby;
    }

    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 char getSex() {
        return sex;
    }

    public void setSex(char sex) {
        this.sex = sex;
    }

    public double getHeight() {
        return height;
    }

    public void setHeight(double height) {
        this.height = height;
    }

    public String getHobby() {
        return hobby;
    }

    public void setHobby(String hobby) {
        this.hobby = hobby;
    }
}

```

```java
package TestFrame;

public class Teacher {
    private String name;
    private double salary;

    public Teacher() {
    }

    public Teacher(String name, double salary) {
        this.name = name;
        this.salary = salary;
    }

    public String getName() {
        return name;
    }

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

    public double getSalary() {
        return salary;
    }

    public void setSalary(double salary) {
        this.salary = salary;
    }
}

```

```java
package TestFrame;


import java.io.FileOutputStream;
import java.io.PrintStream;
import java.lang.reflect.Field;

public class ObjectFrame {
    //目标:保存任意对象的字段和其数据到文件中去
    public static void saveObject(Object obj) throws Exception {
        PrintStream ps = new PrintStream((new FileOutputStream("D:\\javacode\\newtest\\heimatest\\src\\TestFrame\\TestSave.txt",true)));
        //obj是任意对象,到底有多少字段需要保存?---反射获取全部成分
        Class c = obj.getClass();
        String cName = c.getSimpleName();//拿到对象的简名就是类名
        ps.println("-----------" + cName + "------------");
        //从这个类中提取它的全部成员变量
        Field[] fields = c.getDeclaredFields();
        //遍历每个成员变量
        for (Field field : fields){
            field.setAccessible(true);//禁止检查访问控制
            //拿到成员变量的名字
            String name = field.getName();
            //拿到这个成员变量在对象中的数据
            String value = field.get(obj) + "";//基本数据类型不能直接进行强制类型转换为 String,使用(String)转换会报错
            //向文件中保存(打印流)
            ps.println(name + "=" + value);
        }
        ps.close();
    }
}
```

```java
package TestFrame;

import org.junit.Test;

public class TestFrame {
    @Test
    public void save() throws Exception {
        Student s1 = new Student("张三",22,'男',180.6,"篮球、游泳");
        Teacher t1 = new Teacher("王博",1000.0);

        //需求:把任意对象的字段和其对应的值,保存到文件中去。
        ObjectFrame.saveObject(s1);
        ObjectFrame.saveObject(t1);
    }
}
```

```java
结果:
-----------Student------------
name=张三
age=22
sex=男
height=180.6
hobby=篮球、游泳
-----------Teacher------------
name=王博
salary=1000.0

```

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值