Java反射机制

反射机制就是可以把一个类,类的成员(函数,属性),当成一个对象来操作,也就是说,类,类的成员,我们在运行的时候还可以动态地去操作他们.

获得class对象

每个Class被JVM加载后,系统就会为该类生成一个对应的Class对象,通过该Class就可以访问到JVM中的这个类.(这里注意该类可能只是被加载进了内存的方法区,并不一定进行了初始化,关于JVM加载类的知识请自行补充)Java程序中获得Class的对象通常有如下三种方式:

  • 使用Class类的静态方法,该方法需要传入完整的包路径名
  • 调用某个类的class属性来获取该类对应的Class对象.例如Person.class将会返回Person类对应的Class对象.
  • 调用某个对象的getClass()方法,该方法是Object中的一个方法,所以任何类都可以调用.

从Class中获取信息

Class类提供了大量的实例方法来获取Class对象所对应类的详细信息,大概分为
- Method
- Connstructor
- Field
- Annotation
interface,内部类,父类等几乎所有的东西.由于具体的内容太多,无法一一列出,所以这里只进行一些演示,具体的使用可以查看Class类.

1.首先编写我们要使用的Fruit类

public class Fruit {
    private String name;
    private int weight;

    public Fruit() {

    }

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

    public String getName() {
        return name;
    }

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

    public int getWeight() {
        return weight;
    }

    public void setWeight(int weight) {
        this.weight = weight;
    }

}

2.定义一个接口

public interface IColor {
    public void sayShape(String asker);
}

3.编写一个继承Fruit和IColor接口的类

public class Apple extends Fruit implements IColor{
    public String getColor() {
        return color;
    }

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

    private String color;

    @Override
    public void sayShape(String asker) {
        System.out.println("嗨,"+asker+",我是圆形的!");
    }
}

接下来进行演示:

  • 通过反射机制得到类的包名和类名
public class TestDemo {

    public static void main(String[] args) {
        Fruit fruit = new Fruit();
        System.out.println("包名:" + fruit.getClass().getPackage().getName());
        System.out.println("完整类名:" + fruit.getClass().getName());
    }
}

运行结果

包名:com.company.eric.ReflectDemo
完整类名:com.company.eric.ReflectDemo.Fruit
  • 验证所有类都是Class类的实例
public class TestDemo {

    public static void main(String[] args) throws ClassNotFoundException {
        Class<?> class1 = null;
        Class<?> class2 = null;

        class1 = Class.forName("com.company.eric.ReflectDemo.TestDemo");
        System.out.println("包名:" + class1.getClass().getPackage().getName());
        System.out.println("完整类名:" + class1.getClass().getName());

        class2 = Fruit.class;
        System.out.println("包名:" + class2.getClass().getPackage().getName());
        System.out.println("完整类名:" + class2.getClass().getName());

    }
}

输出结果

包名:java.lang
完整类名:java.lang.Class
包名:java.lang
完整类名:java.lang.Class
  • 通过Java反射,使用Class创建对象
public class TestDemo {

    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
        Class cs = Class.forName("com.company.eric.ReflectDemo.Fruit");
        //这里的newInstance使用的时候要保证你的类有无参构造函数
        Fruit fruit = (Fruit) cs.newInstance();
        fruit.setName("Apple");
        fruit.setWeight(5);
        System.out.println("name:" + fruit.getName());
        System.out.println("weight:" + fruit.getWeight());
    }
}

输出结果:

name:Apple
weight:5
  • 通过Java反射机制得到一个类的构造函数,并实现创建带参实例对象
public class TestDemo {

    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
        Class cs = Class.forName("com.company.eric.ReflectDemo.Fruit");

        //获取指定的可访问构造器
        Constructor constructor = cs.getConstructor(String.class, int.class);
        Fruit fruit = (Fruit) constructor.newInstance("Apple", 5);
        System.out.println("name:" + fruit.getName());
        System.out.println("weight:" + fruit.getWeight());

        System.out.println("--------------------");

        //获取所有的构造器,包括私有的
        Constructor[] constructors = cs.getDeclaredConstructors();
        Fruit apple = (Fruit) constructors[0].newInstance();
        apple.setName("Eric");
        apple.setWeight(10);
        System.out.println("name:" + apple.getName());
        System.out.println("weight:" + apple.getWeight());
    }
}

运行结果

name:Apple
weight:5
--------------------
name:Eric
weight:10
  • 通过Java反射获取变量,即使是private也可以,set,get(有点黑科技的感觉)
public class TestDemo {

    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchFieldException {
        Class cs = Class.forName("com.company.eric.ReflectDemo.Fruit");
        Fruit fruit = (Fruit) cs.newInstance();
        Field field = cs.getDeclaredField("name");
        field.setAccessible(true);
        field.set(fruit, "apple");
        System.out.println("name:" + fruit.getName());

        Object obj = cs.newInstance();
        Field field1 = cs.getDeclaredField("weight");
        field1.setAccessible(true);
        field1.setInt(obj, 10);
        System.out.println("name:" + field1.get(obj));
    }
}

输出结果

name:apple
name:10
  • 通过Java反射机制得到类的一些属性: 继承的接口,父类,函数信息,成员信息,类型等
public class TestDemo {

    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchFieldException {
        Class cs = Class.forName("com.company.eric.ReflectDemo.Apple");

        //取得父类名
        Class<?> supreClass=cs.getSuperclass();
        System.out.println("父类名: "+supreClass.getName());
        System.out.println();
        System.out.println("------------------------------------------");
        System.out.println();

        //取得成员变量
        Field []fields=cs.getDeclaredFields();
        for (Field field:fields) {
            System.out.println("类中的成员: "+field.getName());
        }
        System.out.println();
        System.out.println("------------------------------------------");
        System.out.println();

        //取得类方法
        Method []methods=cs.getDeclaredMethods();
        for (Method m :methods) {
            System.out.println("取得类的方法");
            System.out.println("函数名 "+m.getName());
            System.out.println("函数返回类型 "+m.getReturnType());
            System.out.println("函数访问修饰符 "+ Modifier.toString(m.getModifiers()));
            System.out.println("函数代码写法 "+m);
            System.out.println();
        }
        System.out.println();
        System.out.println("------------------------------------------");
        System.out.println();

        //类实现的接口,接口类也属于Class
        Class []interfaces=cs.getInterfaces();
        for (Class<?> c:interfaces) {
            System.out.println("类实现的接口 "+c.getName());
        }
    }
}

输出结果

父类名: com.company.eric.ReflectDemo.Fruit

------------------------------------------

类中的成员: color

------------------------------------------

取得类的方法
函数名 getColor
函数返回类型 class java.lang.String
函数访问修饰符 public
函数代码写法 public java.lang.String com.company.eric.ReflectDemo.Apple.getColor()

取得类的方法
函数名 setColor
函数返回类型 void
函数访问修饰符 public
函数代码写法 public void com.company.eric.ReflectDemo.Apple.setColor(java.lang.String)

取得类的方法
函数名 sayShape
函数返回类型 void
函数访问修饰符 public
函数代码写法 public void com.company.eric.ReflectDemo.Apple.sayShape(java.lang.String)


------------------------------------------

类实现的接口 com.company.eric.ReflectDemo.IColor
  • 通过Java反射机制调用类方法
public class TestDemo {

    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {
        Class cs = Class.forName("com.company.eric.ReflectDemo.Apple");
        Method method = cs.getDeclaredMethod("sayShape", String.class);

        Apple apple = (Apple) cs.newInstance();
        method.invoke(apple, "Eric");
    }
}

输出结果

嗨,Eric,我是圆形的!
  • 通过Java反射机制获得类加载器(默认的加载器是AppClassLoader,有关类加载器的知识不在这里赘述)
public class TestDemo {

    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {
        Class cs = Class.forName("com.company.eric.ReflectDemo.Apple");
        ClassLoader classLoader=cs.getClassLoader();
        System.out.println(classLoader.getClass().getName());
    }
}

输出结果

sun.misc.Launcher$AppClassLoader

以上演示了一些常用的方法,更多的用法请查看各个类的具体api,尤其是Class这个类.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值