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);

结果:

你可能感兴趣的:(基础学习,java)