java反射学习

一、概述

  JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。
  简单来说就是运行时能够获得并使用类的信息的方法叫做反射。

二、可实现功能

  1. 在运行时判断任意一个对象所属的类;
  2. 在运行时构造任意一个类的对象;
  3. 在运行时判断任意一个类所具有的成员变量和方法;
  4. 在运行时调用任意一个对象的方法;
  5. 生成动态代理
  6. 动态获得类型信息(方法、字段、属性。。。)
  7. 动态创建对象(可根据字符串创建对象)
  8. 动态的调用对象或成员

三、class

  众所周知Java有个Object 类,是所有Java 类的继承根源,其内声明了数个应该在所有Java 类中被改写的方法:hashCode()、equals()、clone()、toString()、getClass()等。其中getClass()返回一个Class 对象。

  Class 类十分特殊。它和一般类一样继承自Object,其实体用以表达Java程序运行时的classes和interfaces,也用来表达enum、array、primitive Java types(boolean, byte, char, short, int, long, float, double)以及关键词void。当一个class被加载,或当加载器(class loader)的defineClass()被JVM调用,JVM 便自动产生一个Class 对象

获得Class对象的五种方法
package com.reflect;

public class Animal {
    public String name;
    public static void main(String[] args) throws ClassNotFoundException {
        Animal animal = new Dog();
        System.out.println("小名家里有一只" + animal.name);

        //方法一,通过对象获得
        Class<?> class1 = animal.getClass();
        //方法二,通过字符串获得(包名+类名,可动态创建对象)
        Class<?> class2 = Class.forName("com.reflect.Animal");
        //方法三,通过类的静态成员class获得
        Class<?> class3 = Cat.class;
        //方法四,获得父类型
        Class<?> class4 = class3.getSuperclass();

        //方法五,只能获得基本数据类型
        Class<?> class5 = Double.TYPE;


        System.out.println("class1类名:"+class1.getName());
        System.out.println("class2类名:"+class2.getName());
        System.out.println("class3类名:"+class3.getName());
        System.out.println("class4类名:"+class4.getName());
        System.out.println("class5类名:"+class5.getName());
    }
}

class Dog extends Animal {
    public Dog() {
        this.name = "狗狗";
    }
}

class Cat extends Animal {
    public Cat() {
        this.name = "猫咪";
    }
}

结果

通过Class对象,还可以访问该对象的主要的描述信息。
组成部分访问方法返回值类型说明
包路径getPackage()Package对象获得该类的存放路径
类名称getName()String对象获得该类的名称
继承类getSuperclass()Class对象获得该类继承的类
实现接口getInterfaces()Class型数组获得该类实现的所有接口
构造方法getConstructor()Constructor型数组获得所有权限为public的构造方法
getConstructor(Class<?>…parameterTypes)Constructor对象获得权限为public的指定构造方法
getDeclaredConstructors()Constructor型数组获得所有构造方法,按声明顺序返回
getDeclaredConstructor(Class<?>…parameterTypes)Constructor对象获得指定构造方法
方法getMethods()Method型数组获得所有权限为public的方法
getMethod(String name, Class<?>…parameterTypes)Method对象获得权限为public的方法
getDeclaredMethods()Method型数组获得所有方法,按声明顺序返回
getDeclaredMethods(String name, Class<?>…parameterTypes)Method对象获得指定方法
成员变量getFields()Field型数组获得所有权限为public的成员变量
getField(String name)Field对象获得权限为public的指定成员变量
getDeclaredFields()Field型数组获得所有成员变量,按声明顺序返回
getDeclaredFields(String name)Field对象获得指定成员变量
内部类getClasses()Class型数组获得所有权限为public的内部类
getDeclaredClasses()Class型数组获得所有内部类
内部类的声明类getDeclaringClass()Class对象如果该类为内部类,则返回它的成员类,否则返回null

 

注意:

  在通过getFields()和getMethods()方法依次获得权限为public的成员变量和方法时,将包含从超类中继承到的成员变量和方法;而通过方法getDeclaredFiedls()和getDeclareMethods()只是获得在本类中定义的所有成员变量和方法

四、案例

这里我准备好了一个实体类,接下来的所有的测试都将根据这个实体类来实现
package com.reflect;

public class Fruit {
    String name;
    String color;
    String price;

    public String getName() {
        return name;
    }

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

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }

    public String getPrice() {
        return price;
    }

    public void setPrice(String price) {
        this.price = price;
    }

    public Fruit(String name, String color, String price) {
        this.name = name;
        this.color = color;
        this.price = price;
    }

    public Fruit(String name, String color) {
        this.name = name;
        this.color = color;
    }

    public Fruit() {
    }

    public void getInfo(){
        System.out.println(this.color+"的"+this.name+",价钱是"+this.price+"元/斤");
    }

    public void outInfo(String name,int price){
        System.out.println("这种水果的名字是"+name+",价钱是"+price+"元/斤");
    }

    public void outNull(){
        System.out.println("就是想输出一下。。。");
    }

    @Override
    public String toString() {
        return "Fruit{" +
                "name='" + name + '\'' +
                ", color='" + color + '\'' +
                ", price='" + price + '\'' +
                '}';
    }
}

1、实例化一个对象

//通过反射实例化一个实体类对象
Class<?> demo=Class.forName("com.reflect.Fruit");
Constructor<?>[] con = demo.getConstructors();
Fruit fruit1= (Fruit) demo.newInstance();
//通过构造函数实例对象
Fruit fruit2= (Fruit) con[2].newInstance("苹果","红色","14.5");
Fruit fruit3= (Fruit) con[0].newInstance("橙子","黄色");

System.out.println(fruit1);
System.out.println(fruit2);
System.out.println(fruit3);

结果:

2、获得类所有的构造方法

//获得构造方法
Class<?> demo=Class.forName("com.reflect.Fruit");
//获得所有的构造方法
Constructor<?>[] constructors = demo.getConstructors();
for (int i = 0; i < constructors.length; i++) {
    System.out.println(constructors[i]);
}

结果:

3、获得方法信息

Class<?> demo=Class.forName("com.reflect.Fruit");
Method[] methods = demo.getMethods();
Method[] declaredMethods = demo.getDeclaredMethods();
System.out.println("=========本类所有的方法=========");
for (Method declaredMethod : declaredMethods) {
    System.out.println(declaredMethod);
}
System.out.println("=========父类及本类的所有方法=========");
for (Method method : methods) {
    System.out.println(method);
}

结果:

4、获取成员变量并赋值

Class<?> demo=Class.forName("com.reflect.Fruit");
Fruit fruit= (Fruit) demo.newInstance();
//获取成员变量
Field name=demo.getDeclaredField("name");
Field color=demo.getDeclaredField("color");
Field price=demo.getDeclaredField("price");
//给成员变量赋值
name.set(fruit, "苹果");
color.set(fruit,"红色");
price.set(fruit,"8.8");
fruit.getInfo();

结果:

5、动态调用方法

Class<?> demo=Class.forName("com.reflect.Fruit");
Fruit fruit= (Fruit) demo.newInstance();
//动态获得方法名称及参数类型
Method method=demo.getDeclaredMethod("outInfo", String.class, Integer.TYPE);
//动态实现方法
method.invoke(fruit,"榴莲",39);

结果:

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值