Java反射

基本概念

在计算机科学中,反射是指计算机程序在运行时(Run time)可以访问、检测和修改它本身状态或行为的一种能力。在Java中,反射允许在编译期间不知道接口的名称,字段、方法的情况下,在运行时检查类、接口、字段和方法。它还允许实例化新对象、修改成员变量和调用方法。

使用

要在Java中使用反射,就必须使用到Class类。在面向对象的世界里,万事万物皆对象。所以类也是对象,类是java.lang.Class的实例化对象。也就是在Java中任何一个类都是都是Class类的实例化对象。在进行反射操作前必须先取得该类的类类型(即该类对应的Class类的实例化对象),有三种方法可以完成此项操作:
假定需要进行反射操作的类如下:

class A{
    private String name;
    public int age;
    public String getName(){
        return this.name;
    }
    public A(){}
    public A(String name, int age){
        this.name = name;
        this.age = age;
    }
    public void print(int a, int b){
        System.out.println(a + b);
    }
    public void print(String a, String b){
        System.out.println(a + b);
    }
}
  1. 通过任何一个类中都有隐含的静态成员变量class取得
Class c1 = A.class;
  1. 若已知某个类的实例化对象,通过getClass方法取得
A a = new A();
Class c2 = a.getClass();
  1. 通过Class类提供的forName(包名.类名称)方法取得(此方法可用于类的动态加载,详情见后)
Class c3 = Class.forName("A");

注: Classc1c2c3

测试代码

package practicve.reflect;

import java.lang.reflect.Field;
import java.lang.reflect.Method;

/**
 * Created by lin_y on 2017/6/17.
 */

class A{
    private String name;
    public String getName(){
        return this.name;
    }
    public void print(int a, int b){
        System.out.println(a + b);
    }
    public void print(String a, String b){
        System.out.println(a + b);
    }
}
public class Refelct {
    public static void main(String [] args) throws ClassNotFoundException {
        //  方式一:通过类中的隐含静态变量class获取A类的类类型(Class类对象)
        Class c1 = A.class;
        // 方式二:通过A的对象a调用getClass方法获取A的类类型(Class类对象)
        A a = new A();
        Class c2 = a.getClass();
        // 方式三:使用Class类的静态方法forName获取A的类类型(Class类对象)
        Class c3 = Class.forName("A");
        // 一个类只可能是Class类的一个实例对象(c1、c2、c3相等)
        System.out.println(c1 == c2 && c2 == c3);
    }
}

运行结果

这里写图片描述

获取Class的实例对象后,便可完成该类的反射操作。下面主要介绍三种反射操作:
1. 构造函数的反射操作
2. 成员变量的反射操作
3. 方法的反射操作

  1. 构造方法的反射操作
class A{
    private String name;
    public int age;
    public String getName(){
        return this.name;
    }
    public A(){}
    public A(String name, int age){
        this.name = name;
        this.age = age;
    }
    public void print(int a, int b){
        System.out.println(a + b);
    }
    public void print(String a, String b){
        System.out.println(a + b);
    }
    public String toString(){
        return "name:" + this.name + "  age:" + this.age;
    }
}
public class Refelct {
    public static void main(String [] args) throws Exception {
        // 方式三:使用Class类的静态方法forName获取A的类类型(Class类对象)
        Class c = Class.forName("practicve.reflect.A");
        // 获取含参构造方法
        Constructor cs = c.getConstructor(String.class, int.class);
        // 调用构造方法实例化A类对象
        Object obj = cs.newInstance("zhangsan", 20);
    System.out.println(obj.toString());
    }
}

程序运行结果

这里写图片描述

  1. 成员变量的反射操作
package practicve.reflect;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

/**
 * Created by lin_y on 2017/6/17.
 */

class A{
    private String name;
    public int age;
    public String getName(){
        return this.name;
    }
    public A(){}
    public A(String name, int age){
        this.name = name;
        this.age = age;
    }
    public void print(int a, int b){
        System.out.println(a + b);
    }
    public void print(String a, String b){
        System.out.println(a + b);
    }
    public String toString(){
        return "name:" + this.name + "  age:" + this.age;
    }
}
public class Refelct {
    public static void main(String [] args) throws Exception {
        // 方式三:使用Class类的静态方法forName获取A的类类型(Class类对象)
        Class c = Class.forName("practicve.reflect.A");
        // 获取A类中的成员变量
        Field name = c.getDeclaredField("name");
        Field age = c.getDeclaredField("age");
        // 允许改变private变量
        name.setAccessible(true);
        A a = new A();
        // 变量反射操作
        name.set(a, "zhangsan");
        age.set(a, 20);
    System.out.println(a.toString());
    }
}

程序运行结果

这里写图片描述

  1. 方法的反射操作
package practicve.reflect;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

/**
 * Created by lin_y on 2017/6/17.
 */

class A{
    private String name;
    public int age;
    public String getName(){
        return this.name;
    }
    public A(){}
    public A(String name, int age){
        this.name = name;
        this.age = age;
    }
    public void print(int a, int b){
        System.out.println(a + b);
    }
    public void print(String a, String b){
        System.out.println(a + b);
    }
    public String toString(){
        return "name:" + this.name + "  age:" + this.age;
    }
}
public class Refelct {
    public static void main(String [] args) throws Exception {
        // 方式三:使用Class类的静态方法forName获取A的类类型(Class类对象)
        Class c = Class.forName("practicve.reflect.A");
        // 获取A类中的方法
       Method m1 = c.getDeclaredMethod("print", String.class, String.class);
       Method m2 = c.getDeclaredMethod("print", int.class, int.class);
       A a = new A();
       // 方法的调用
        m1.invoke(a, "12", "34");
        m2.invoke(a, 12, 34);
    }
}

程序运行结果
这里写图片描述

注:

附:动态加载

基本概念:使用 new 创建对象是静态加载类,在编译时刻就需要加载所有的可能使用到的类。而动态加载类,是在运行时刻加载所需的类。

比如说,要写一个Office软件,里面包含多种功能,便可以使用动态加载类来实现 线 ,具体实现见如下例子:

OfficeAble接口

package practicve.reflect;

/**
 * Created by lin_y on 2017/6/17.
 */
public interface OfficeAble {
    public void print();
}

Office主类

package practicve.reflect;

/**
 * Created by lin_y on 2017/6/17.
 */
public class Office {
    public static void main(String [] args) throws Exception {
        OfficeAble office = (OfficeAble) Class.forName(args[0]).newInstance();
        office.print();
    }
}

Word功能

package practicve.reflect;

/**
 * Created by lin_y on 2017/6/17.
 */
public class Word implements OfficeAble {
    @Override
    public void print() {
        System.out.println("Word start ...");
    }
}

Excel功能

package practicve.reflect;

/**
 * Created by lin_y on 2017/6/17.
 */
public class Excel implements OfficeAble{
    @Override
    public void print() {
        System.out.println("Excel start ...");
    }
}

程序运行时args[0]参数为practicve.reflect.Word,程序运行结果为:
这里写图片描述

注: 1.使;2.使线

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值