java高级特性之反射

前言:
下面是个student类,我想获得此类中信息,除了用正常的new对象的方法,我们还可以用反射的方式获取。(本文下面讲解都以Student类为示例)

public class Student {
  private String name;
  private Integer age;
  private String gender;
  private String mobile;
  private  String address;

    
    public Student(){}
    public Student(String name, Integer age, String gender, String mobile, String address) {
        this.name = name;
        setAge(age);
        setGender(gender);
        this.gender = gender;
        this.mobile = mobile;
        this.address = address;
    }

    public String getName() {
        return name;
    }

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

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age<=18?18:age;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
    this.gender = (!gender.equals("男")&&!gender.equals("女"))?"男":gender;
    }

    public String getMobile() {
        return mobile;
    }

    public void setMobile(String mobile) {
        this.mobile = mobile;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", gender='" + gender + '\'' +
                ", mobile='" + mobile + '\'' +
                ", address='" + address + '\'' +
                '}';
    }
}

一.什么是反射

反射就是:在程序运行时动态解析类的内部信息(注解,属性,方法)。
所以反射的前提就是:必须先得到代表的字节码的Class,Class类用于表示.class文件(字节码)

二.怎么用反射

1.获取目标类型的Class对象
方法有三种
第一种:Class c1 = Student.class;
第二种:Student stu = new Student();
Class c2 = stu.getClass();
第三种:Class c3 = Class.forName(“refection.Student”);
此方法要处理ClassNotFoundException异常,防止路径下没有此类

//方式一
Class c1 = Student.class;
System.out.println("方式一:"+c1);
//方式二
Student stu = new Student();
Class c2 = stu.getClass();
System.out.println("方式二:"+c2);
//方式三(此方法要处理异常)
Class c3 = Class.forName("refection.Student");
System.out.println("方式三:"+c3);

输出结果为:

方式一:class refection.Student
方式二:class refection.Student
方式三:class refection.Student

2.获取类名
法一:String fullPathName = c1.getName();//获取类的全路径名称
法二:String simpleName = c1.getSimpleName();//获取类的简名称,也就是类名

String name = c1.getName();//获取类的全路径
String simpleName = c1.getSimpleName();//获取类的简名称
System.out.println("name为:"+name);
System.out.println("simpleName为:"+simpleName);

代码执行结果

name为:refection.Student
simpleName为:Student

3.获取目标类型的Class对象中的构造方法
第一种:获取无参构造
Constructor noCons = c1.getConstructor();
第二种:获取有参构造方法
Constructor hasCons = c1.getConstructor(String.class, Integer.class,String.class,String.class,String.class)
注意:看我Student类中成员变量的类型都不是基本类型。

//获取类的构造方法
Constructor noCons = c1.getConstructor();//获取无参构造
Constructor hasCons = c1.getConstructor(String.class, Integer.class,String.class,String.class,String.class);
System.out.println(noCons);
System.out.println(hasCons);

结果为:

public refection.Student()
public refection.Student(java.lang.String,java.lang.Integer,java.lang.String,java.lang.String,java.lang.String)

4.获取目标类型的Class对象中的自定义属性(成员变量Field)
Field[] fs = c1.getDeclaredFields();//获取类中所有的自定义的属性(返回的是个数组)

int modeifiedNum = f.getModifiers();//获取属性访问修饰整数(返回是个整数,0代表default,1代表public,2代表private,4代表protected

String typeName = c.getName();//获取属性的类型名称

String fieldName = f.getName();//获取属性的名称

代码如下

//获取类中自定义属性
int modeifiedNum ;//属性访问修饰整数
Class c ;//属性的类型信息
String typeName ;//属性的类型名称
String fieldName ;//属性的名称
Field[] fs = c1.getDeclaredFields();//获取类中所有的自定义的属性
for (Field f : fs) {
     modeifiedNum = f.getModifiers();//获取属性访问修饰整数
     c = f.getType();//获取属性的类型信息
     typeName = c.getName();//获取属性的类型名称
     fieldName = f.getName();//获取属性的名称
    System.out.println("访问修饰符:"+modeifiedNum);
    System.out.println("属性的类型信息:"+c);
    System.out.println("属性的类型名称:"+typeName);
    System.out.println("属性的名称:"+fieldName);
    System.out.println("==========================");
}

运行结果如下

访问修饰符:2
属性的类型信息:class java.lang.String
属性的类型名称:java.lang.String
属性的名称:name
==========================
访问修饰符:1
属性的类型信息:class java.lang.Integer
属性的类型名称:java.lang.Integer
属性的名称:age
==========================
访问修饰符:0
属性的类型信息:class java.lang.String
属性的类型名称:java.lang.String
属性的名称:gender
==========================
访问修饰符:4
属性的类型信息:class java.lang.String
属性的类型名称:java.lang.String
属性的名称:mobile
==========================
访问修饰符:2
属性的类型信息:class java.lang.String
属性的类型名称:java.lang.String
属性的名称:address

5.获取目标类型的Class对象中的相关的方法
Method[] ms = c1.getDeclaredMethods();//获取类中所有的方法
String methodName = m.getName();//获取方法的名称
Class cm = m.getReturnType();//获取方法的返回类型
String returnType = cm.getName();//获取方法返回类型的名称
Class<?>[] parameterTypes = m.getParameterTypes();//获取方法所有参数类型(数组)

//获取类中的自定义方法
String methodName ;
Class cm;//方法的返回类型
String returnType;//方法返回类型的名称
Class<?>[] parameterTypes;//方法所有参数类型
Method[] ms = c1.getDeclaredMethods();
for (Method m : ms) {
    methodName = m.getName();//获取方法的名称
    System.out.println("方法名称为:"+methodName);
    cm = m.getReturnType();//获取方法的返回类型
    System.out.println("返回类型:"+cm);
    returnType = cm.getName();//获取方法返回类型的名称
    System.out.println("返回类型的名称:"+returnType);
    parameterTypes = m.getParameterTypes();//获取方法所有参数类型
    for (Class<?> t : parameterTypes) {
        System.out.println("方法中的參數为:"+t);
    }
    System.out.println("=============================");
}

运行结果

方法名称为:toString
返回类型:class java.lang.String
返回类型的名称:java.lang.String
=============================
方法名称为:getAddress
返回类型:class java.lang.String
返回类型的名称:java.lang.String
=============================
方法名称为:getName
返回类型:class java.lang.String
返回类型的名称:java.lang.String
=============================
方法名称为:setName
返回类型:void
返回类型的名称:void
方法中的參數為:class java.lang.String
=============================
方法名称为:getAge
返回类型:class java.lang.Integer
返回类型的名称:java.lang.Integer
=============================
方法名称为:setAge
返回类型:void
返回类型的名称:void
方法中的參數為:class java.lang.Integer
=============================
方法名称为:getMobile
返回类型:class java.lang.String
返回类型的名称:java.lang.String
=============================
方法名称为:setMobile
返回类型:void
返回类型的名称:void
方法中的參數為:class java.lang.String
=============================
方法名称为:getGender
返回类型:class java.lang.String
返回类型的名称:java.lang.String
=============================
方法名称为:setGender
返回类型:void
返回类型的名称:void
方法中的參數為:class java.lang.String
=============================
方法名称为:setAddress
返回类型:void
返回类型的名称:void
方法中的參數為:class java.lang.String
=============================

三.运用反射给类中的属性赋值

从上面我们知道了

类名用途
Class代表类的实体,在运行的Java应用程序中表示类和接口
Fields代表类的成员变量(类属性)
Method代表类的方法
Constructor代表类的构造方法

下面我们就来运用一下,调用类中的方法,给类属性赋值
1.创建对象
利用无参构造创建对象
T t = (T)c.newInstance();
利用无参构造创建函数
Constructor cons = c.getConstructor(Class<?> …parameter Types); T t = (T)cons.newInstance(Object…parameters);

Student t = (Student)c3.newInstance();//利用无参构造创建对象,处理异常
Constructor cons = c3.getConstructor(String.class, Integer.class, String.class, String.class, String.class);//获取构造器
Student t1 = (Student)cons.newInstance("hello",17,"1","2","3");//利用有参构造,处理异常

2.给姓名赋值

Method m = c3.getDeclaredMethod("setName",String.class);//获取setName方法
m.setAccessible(true);//防止方法时私有的,如果方法是私有的设置为true
m.invoke(t,"你猜");//给调用方法,赋值
System.out.println(t);
m = c3.getMethod("getName");//获取查值的方法
String  name = (String) m.invoke(t);
System.out.println("姓名为:"+name);

其中:m.invoke()方法作用是传递object对象及参数调用该对象对应的方法;
m.setAccessible(true);//设置方法的可见性

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值