Java 反射机制详解(下)

续:Java 反射机制详解(上)

三、怎么使用反射 

  想要使用反射机制,就必须要先获取到该类的字节码文件对象(.class),通过字节码文件对象,就能够通过该类中的方法获取到我们想要的所有信息(方法,属性,类名,父类名,实现的所有接口等等),每一个类对应着一个字节码文件也就对应着一个Class类型的对象,也就是字节码文件对象。

  获取字节码文件对象的三种方式。

   1、Class class1= Class.forName("全限定类名");  //通过Class类中的静态方法forName,直接获取到一个类的字节码文件对象,此时该类还是源文件阶段,并没有变为字节码文件。

   2、Class class2= User.class;    //当类被加载成.class文件时,此时Person类变成了.class,在获取该字节码文件对象,也就是获取自己, 该类处于字节码阶段

   3、Class class3= user.getClass();    //通过类的实例获取该类的字节码文件对象,该类处于创建对象阶段。

代码实例:

//User类还没有加载,在源文件阶段 获取其字节码文件对象
Class class1 =Class.forName("com.reflect.test.User");
System.out.println("第一种:"+class1.getName());
//可以根据 实例对象获取我们想要的信息
Class class2 = User.class;
System.out.println("第二种:"+class2.getName());

User user = new User();
Class class3 = user.getClass();
System.out.println("第三种:"+class3.getName());
}

输出:
第一种:com.reflect.test.User
第二种:com.reflect.test.User
第三种:com.reflect.test.User

获取字节码文件对象

 有了字节码文件对象才能获得类中所有的信息,我们在使用反射获取信息时,也要考虑使用上面哪种方式获取字节码对象合理,视不同情况而定。下面介绍Class类的功能。

首先生成一个User类对象

package com.reflect.test;

public class User {

    private String name ;
    private int age;
    private String sex;

    public User() {
    }

    public User(String name, int age, String sex) {
        this.name = name;
        this.age = age;
        this.sex = sex;
    }

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    @Override
    public String toString() {
        return "User{" +
                "name=‘" + name + ‘\‘‘ +
                ", age=" + age +
                ", sex=‘" + sex + ‘\‘‘ +
                ‘}‘;
    }
}

User.java

3.1 通过字节码对象创建实例对象

public  static void main(String[] args) throws  ClassNotFoundException,InstantiationException,IllegalAccessException{    //User类还没有加载,在源文件阶段 获取其字节码文件对象    Class classz =Class.forName("com.reflect.test"); //forname 里面的参数完整文件路径,如果查不到改路径下的文件 会报 classNotFound异常    //创建实例,    User user = (User) classz.newInstance();    //可以根据 实例对象获取我们想要的信息}

3.2获取指定构造器方法。constructor对象

知道对象构造函数的参数情况下,可以直接获取指定构造函数。

//User类还没有加载,在源文件阶段 获取其字节码文件对象
 Class class1 =Class.forName("com.reflect.test.User");
//获取无参构造函数
Constructor constructor1 = class1.getConstructor();
//获取有参构造函数
Constructor constructor2 = class1.getConstructor(String.class,int.class,String.class);
User user1=(User)constructor1.newInstance();
System.out.println("user1:  " + user1);
User user2 = (User) constructor2.newInstance("张三",23,"男");
System.out.println("user1:  "+ user2);

输出:

  user1: User{name=‘null‘, age=0, sex=‘null‘}
  user1: User{name=‘张三‘, age=23, sex=‘男‘}

如果不知道 User类有哪些构造方法,以及参数,可以这样获取全部构造方法

//User类还没有加载,在源文件阶段 获取其字节码文件对象
Class class1 =Class.forName("com.reflect.test.User");
//获取所有构造方法
Constructor[] constructors = class1.getConstructors();
//遍历所有构造方法
int index = 0;
for(Constructor constructor : constructors){
Class[] parameterTypes = constructor.getParameterTypes();
index =index+1;
System.out.println("第" + index +"个构造函数");
for (Class parameterType : parameterTypes){
    //获取构造函数中的参数类型
    System.out.print(parameterType.getName()+",");
}输出:

第1个构造函数
第2个构造函数
java.lang.String,int,java.lang.String,

3.2获取成员变量并使用。Field对象

获取指定成员变量

//User类还没有加载,在源文件阶段 获取其字节码文件对象
Class class1 =Class.forName("com.reflect.test.User");
//获取实例对象
User user = (User) class1.newInstance();
//获取成员变量class1.getField(name); 通过name获取指定变量
// 如果变量属性是私有的 那么应该使用class1.getDeclaredField(name);
Field field = class1.getDeclaredField("name");
//因为属性是私有的,获得对象属性后,还要打开其私有权限
field.setAccessible(true);  // 这里也变相的破解了 面向对象的封装性
//对其变量进行操作
field.set(user,"张三");
//
System.out.println(field.get(user));
System.out.println(user.getName());
输出:
张三
张三

Class.getField(String)方法可以获取类中的指定字段(可见的), 如果是私有的可以用getDeclaedField("name")方法获取,通过set(obj, "李四")方法可以设置指定对象上该字段的值, 如果是私有的需要先调用setAccessible(true)设置访问权限,用获取的指定的字段调用get(obj)可以获取指定对象中该字段的值

获取全部属性 变量

//User类还没有加载,在源文件阶段 获取其字节码文件对象
Class class1 =Class.forName("com.reflect.test.User");
//获取实例对象
User user = (User) class1.newInstance();
user.setName("zhangsan");
user.setAge(23);
user.setSex("男");
//获取全部成员变量
Field[] fields = class1.getDeclaredFields();

for ( Field field : fields){
    field.setAccessible(true);
    System.out.println(field.get(user));
}输出:zhangsan23男

3.3 获得成员方法并使用。Method对象

//User类还没有加载,在源文件阶段 获取其字节码文件对象
Class class1 =Class.forName("com.reflect.test.User");
//获取实例对象
User user = (User) class1.newInstance();
user.setAge(23);
user.setSex("男");
/**
 * Method getMethod(String name, Class<?>... parameterTypes)
 * name : 为方法名字
 * parameterTypes:方法的参数,为class类型,比如参数类型为String,则填string.class
 * 没有则不填
 */
/**
 * Object invoke(Object obj, Object... args)
 * obj:方法的对象
 * args:实际的参数值,没有则不填
 */
Method method1 = class1.getMethod("getAge");
System.out.println("method1 方法:" +method1.getName());
System.out.println("调用方法 : "+method1.invoke(user));
Method method2 = class1.getMethod("getSex");
System.out.println("method2 方法:" +method2.getName());
System.out.println("调用方法 : "+method2.invoke(user));
//我们将 User 类的setName()方法 改为私有的private void setName(String name) {this.name = name; }

Method method3 = class1.getDeclaredMethod("setName", String.class);
method3.setAccessible(true);
method3.invoke(user,"zhangsan"); //可以调用 user对象的 私有方法setName
System.out.println("user.getName :" + user.getName()); // 获取 name属性值

输出:
method1 方法:getAge
调用方法 : 23
method2 方法:getSex
调用方法 : 男
user.getName :zhangsan

Class.getMethod(String, Class...) 和 Class.getDeclaredMethod(String, Class...)方法可以获取类中的指定方法,    

如果为私有方法,则需要打开一个权限。setAccessible(true);

用invoke(Object, Object...)可以调用该方法,

同理可以 获取全部方法

//User类还没有加载,在源文件阶段 获取其字节码文件对象
Class class1 =Class.forName("com.reflect.test.User");
//获取实例对象
User user = (User) class1.newInstance();
user.setAge(23);
user.setSex("男");

Method [] methods = class1.getDeclaredMethods();
for (Method method : methods){
    method.setAccessible(true);
    System.out.println("方法名:"+method.getName());//获取 方法名
    Class [] parameterTypes = method.getParameterTypes();//这里又回到了上面的获取参数代码
    for (Class parameterType : parameterTypes){
    System.out.println("获取参数名:"+parameterType.getName());
    }

}
输出:
方法名:toString
方法名:getName
方法名:setName
获取参数名:java.lang.String
方法名:getSex
方法名:getAge
方法名:setSex
获取参数名:java.lang.String
方法名:setAge
获取参数名:int

3.4 获得该类的所有接口

    Class[] getInterfaces():确定此对象所表示的类或接口实现的接口

    返回值:接口的字节码文件对象的数组

原文地址:https://www.cnblogs.com/justBobo/p/10924589.html

时间: 2024-10-25 17:22:38

Java 反射机制详解(下)的相关文章

Java反射机制详解

Java反射机制详解 Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象的方法的功能称为Java语言的反射机制. 1.关于Class 1.Class是一个类,一个描述类的类(也就是描述类本身),封装了描述方法的Method,描述字段的Filed,描述构造器的Constructor等属性    2.对象照镜子后(反射)可以得到的信息:某个类的数据成员名.方法和构造器.某个类到底实现

【转载】Java反射机制详解

转自:http://baike.xsoftlab.net/view/209.html#3_8 1反射机制是什么 反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制. 2反射机制能做什么 反射机制主要提供了以下功能: 在运行时判断任意一个对象所属的类: 在运行时构造任意一个类的对象: 在运行时判断任意一个类所具有的成员变量和方法: 在运行时调用任意一个

Java反射机制详解(3) -java的反射和代理实现IOC模式 模拟spring

IOC(Inverse of Control) 可翻译为“控制反转”,但大多数人都习惯将它称为“依赖注入”.在Spring中,通过IOC可以将实现类.参数信息等配置在其对应的配置文件中,那么当 需要更改实现类或参数信息时,只需要修改配置文件即可,这种方法在上例的基础上更进一步的降低了类与类之间的耦合.我们还可以对某对象所需要的其它对象进 行注入,这种注入都是在配置文件中做的,Spring的IOC的实现原理利用的就是Java的反射机制, Spring还充当了工厂的角色,我们不需要自己建立工厂类.S

java反射机制详解和应用

1反射机制是什么 反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制. 2反射机制能做什么 反射机制主要提供了以下功能: 在运行时判断任意一个对象所属的类: 在运行时构造任意一个类的对象: 在运行时判断任意一个类所具有的成员变量和方法: 在运行时调用任意一个对象的方法: 生成动态代理. 3反射机制的相关API 通过一个对象获得完整的包名和类名 pub

[转]Java反射机制详解

目录 1反射机制是什么 2反射机制能做什么 3反射机制的相关API ·通过一个对象获得完整的包名和类名 ·实例化Class类对象 ·获取一个对象的父类与实现的接口 ·获取某个类中的全部构造函数 - 详见下例 ·通过反射机制实例化一个类的对象 ·获取某个类的全部属性 ·获取某个类的全部方法 ·通过反射机制调用某个类的方法 ·通过反射机制操作某个类的属性 ·反射机制的动态代理 4反射机制的应用实例 ·在泛型为Integer的ArrayList中存放一个String类型的对象. ·通过反射取得并修改数

java反射机制详解 及 Method.invoke解释 getMethod

JAVA反射机制 JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法:这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制.Java反射机制主要提供了以下功能: 在运行时判断任意一个对象所属的类:在运行时构造任意一个类的对象:在运行时判断任意一个类所具有的成员变量和方法:在运行时调用任意一个对象的方法:生成动态代理.1. 得到某个对象的属性 public Object getProperty(Obje

java反射机制详解 及 Method.invoke解释

JAVA反射机制 JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法:这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制.Java反射机制主要提供了以下功能: 在运行时判断任意一个对象所属的类:在运行时构造任意一个类的对象:在运行时判断任意一个类所具有的成员变量和方法:在运行时调用任意一个对象的方法:生成动态代理.1. 得到某个对象的属性 Java代码   public Object getProp

Java反射机制详解(1) -反射定义

---恢复内容开始--- 首先,我们在开始前提出一个问题: 1.在运行时,对于一个java类,能否知道属性和方法:能否去调用它的任意方法? 答案是肯定的. 本节所有目录如下: 什么是JAVA的反射机制 JDK中提供的Reflection API JAVA反射机制提供了什么功能 获取类的Class对象 获取类的Fields 获取类的Method 获取类的Constructor 新建类的实例        Class<T>的函数newInstance        通过Constructor对象的

Java反射机制详解一

1反射机制是什么 反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制. 在面向对象的世界里,万事万物皆对象.在java语言里,静态的成员,普通数据类型是不是对象呢? 类又是谁的对象呢? 首先类是对象,类是java.lang.Class类的实例对象. 新创建一个Foo类 Foo这个类也是一个实例对象,是Class类的实例对象,这个对象在官网被称为(cl