Java深入理解之反射

每一个类都有一个class对象,包含了与类有关的信息,当编译一个新类时,会产生一个同名的.class文件,该文件内容保持着class对象。

简而言之,通过反射,我们可以在运行时获得程序或程序集中每一个类型的成员和成员的信息。程序中一般的对象的类型都是在编译期就确定下来的,而 Java 反射机制可以动态地创建对象并调用其属性,这样的对象的类型在编译期是未知的。所以我们可以通过反射机制直接创建对象,即使这个对象的类型在编译期是未知的。

反射可以提供运行时的类信息,并且这个类可以在运行时才加载进来,甚至在编译时期该类的 .class 不存在也可以加载进来。

Class 和 java.lang.reflect 一起对反射提供了支持,java.lang.reflect 类库主要包含了以下三个类:

  1. Field:可以使用get()和set()方法读取和修改Field对象关联的字段
  2. Method:可以使用 invoke() 方法调用与 Method 对象关联的方法;
  3. Constructor:可以用 Constructor 创建新的对象

反射的基本运用:
1.获取class对象

 
/**使用class类的forname静态方法
*/
public static Class<?> forName(String className)
``` 
比如在 JDBC 开发中常用此方法加载数据库驱动:
```java
 Class.forName(driver);
//直接获取某一个对象的class
Class<?> klass = int.class;
Class<?> classInt = Integer.TYPE;

 


//调用某个对象的getclass()方法,比如:
StringBuilder str = new StringBuilder("123");
Class<?> klass = str.getClass();

2.通过反射来生成对象主要有两种方式

//1.使用Class对象的newInstance()方法来创建Class对象对应类的实例。


Class<?> c = String.class;
Object str = c.newInstance();


// 2.先通过Class对象获取指定的Constructor对象,再调用Constructor对象的newInstance()方法来创建实例。这种方法可以用指定的构造器构造类的实例。

//获取String所对应的class对象
class<?> c=String.class;
//获取String类带一个String参数的构造器
Constructor constructor = c.getConstructor(String.class);
//获取构造器创建实例
Object obj = constructor.newInstance("dsds");
System.out.println(obj);

 下面是一个面试可以回答反射的例子:
   实体类:

package com.aixs.basic.reflect;

/**
 * @author aixscode.github.io
 * @date 2019/1/21 9:29
 */
public class Robot {

    private  String name;

    public void sayHi(String helloSentence)
    {

        System.out.println(helloSentence+" "+name);
    }
    private String  throwhello(String tag)
    {
        return  "Hello "+tag;
    }

}

 反射实例:

package com.aixs.basic.reflect;

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

/**
 * @author aixscode.github.io
 * @date 2019/1/21 9:31
 */
public class ReflectSample {

    public  static  void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {

        //通过全类名找到Class
        Class c= Class.forName("com.aixs.basic.reflect.Robot");

        //创建出类实例
        Robot r=(Robot) c.newInstance();
        //打印类的全类名
        System.out.println("Class name is"+c.getName());
         
        
        //调用Robot throwhello 方法(私有)
        // 1.构建Method对象 调用getDeclaredMethod
        // 2.设置Accessible 为true
        // 3.invoke()
        Method getHello = c.getDeclaredMethod("throwhello", String.class);//除去继承和实现其他类的方法的的所有方法
        
        getHello.setAccessible(true);
        Object str= getHello.invoke(r,"bob");
        System.out.println("gethello result is "+ str);
        
        // getMethod 调用public方法
        Method sayHi = c.getMethod("sayHi", String.class);//除去私有的其他方法(包括继承实现其他类的方法)

        sayHi.invoke(r, "welcome");
        
        //得到成员
        Field name = c.getDeclaredField("name");
        name.setAccessible(true);
        name.set(r,"Alice");
        sayHi.invoke(r, "welcome");

    }
}

 

运行结果:
 

Class name iscom.aixs.basic.reflect.Robot
gethello result is Hello bob
welcome null
welcome Alice

 

 

 

 

 

 

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值