Java反射学习

作者: 皮球二二 | 来源:发表于2016-05-31 16:27 被阅读219次

反射其实是一个很重要的概念。
引用百度百科的概念:
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
说白了就是在哪都能调用起来任何一个类对象

反射相关类介绍

  1. Class
    它表示正在运行的Java应用程序中的类和接口
  2. Field
    提供有关类或接口的属性信息,以及对它的动态访问权限
  3. Constructor
    提供关于类的单个构造方法的信息以及对它的访问权限
  4. Method
    提供关于类或接口中某个方法的信息

实现步骤

反射实现起来跟一般的类实例化对象然后调用方法、属性流程是一样的,具体我们还是跟着范例来学习

首先先上需要反射操作的类

public interface SkinColor {    
    public static int age=20;       
    void color(int color);
}

public class Person implements SkinColor {    
    public int sex=-1;    
    private String name;    
    private Person(int sex, String name) {      
        this.sex = sex;        
        this.name = name;    
    }    
    public Person() {        
        new Person(0, "default");    
    }    
    public int getSex() {        
        return sex;    
    }    
    public void setSex(int sex) {        
        this.sex = sex;    
    }    
    public String getName() {        
        return name;    
    }    
    public void setName(String name) {        
        this.name = name;    
    }

    @Override
    public void color(int color) {}

    private class Family {    
        String familyName="default family";    
        public Family(String familyName) {        
            this.familyName = familyName;    
        }    
        public Family() {    

        }    
        public String getFamilyName() {        
            return familyName;    
        }    
        public void setFamilyName(String familyName) {        
            this.familyName = familyName;    
        }
    }
}
  1. 对象初始化
Class class_1=Class.forName("com.renyu.demo.Person");
Class class_2=Person.class;
Class class_3=new Person().getClass();
Constructor constructor_1=class_1.getConstructor(null);    
Person person= (Person) constructor_1.newInstance();    

虽然看上去我们有三种实例化对象的方法,但是我个人建议大家记住第一种就行了,因为第二种跟第三种情况不适用于私有类的实例化
来看看私有内部类的实例化

Class class_family=Class.forName("com.renyu.demo.Person$Family");

内部类的访问需要用$来获取,这个熟悉java的同学应该很清楚
下面构造函数的获取方式跟之前相比就有很大的不同了,我们来看一下

for (Constructor constructor1 : class_family.getDeclaredConstructors()) {    
    System.out.println(constructor1.toString());
}

看看打印出来的是什么玩意

public com.renyu.demo.Person$Family(com.renyu.demo.Person,java.lang.String)
public com.renyu.demo.Person$Family(com.renyu.demo.Person)

看到没有,外部类也进去了。一开始我没有注意这个地方,然后一直报错

Constructor constructor1=class_family.getConstructor(Person.class, String.class);
Object family=constructor1.newInstance(person, "123");

这样我们就完美的实例化内部类了
如果你存在父类,那么你可以这样获取class对象

class_.getSuperclass()

总结一下

  • 当你构造方法有参数的话,那么把它的类型放到getConstructor里面,如果没有的话,就直接传null。同样在newInstance一样,无参构造方法就不传东西了,有参构造方法就把相应初始化的值给放进去即可。当然你可以直接绕过构造方法,因为默认是调用无参构造方法的,所以直接class.newInstance()也是可以的
  • 如果你没有写无参构造方法,直接写了有参构造方法的话,那么之前的逻辑就有问题,会抛出一系列异常出来,所以在使用Class实例化其他类的对象的时候,一定要定义无参构造方法

属性调用

目前有2种获取属性的方法

Field[] fields=class_1.getFields();
Field[] fields=class_1.getDeclaredFields();

看下这两种结果的区别

for (Field field : fields) {    
    System.out.println(field.getName()+" "+field.getType());
}

第一种情况

sex int
age int

第二种情况

sex int
name class java.lang.String

显而易见了,getDeclaredFields是获取当前类所有的属性(public或者private全都算),getFields是获取所有(包括父类、接口)public属性

这样你应该知道可以通过何种方法去修改相应属性的值

比如我要改name属性的初始化值并验证是否成功,就得用getDeclaredField去获得这个属性

Field name=class_1.getDeclaredField("name");
name.setAccessible(true);
name.set(person, "Hello");
String value1=name.get(person).toString();
System.out.println(value1);

打印出来就是一个hello

方法调用

同属性类似,一样有2种方式获取当前类所有的方法

class_1.getMethods();
class_1.getDeclaredMethods();

看下这两种结果的区别

for (Method method : methods) {    
    System.out.print(method.getName()+" "+method.getReturnType()+" ");    
    int i=0;    
    for (Class<?> aClass : method.getParameterTypes()) {       
        i++;        
        System.out.print("params"+i+" "+aClass.toString()+" ");    
    }    
    System.out.println("");    
    System.out.println("*********");
}

第一种情况

getName class java.lang.String 
*********
setName void params1 class java.lang.String 
*********
color void params1 int 
*********
getSex int 
*********
setSex void params1 int 
*********
Disconnected from the target VM, address: '127.0.0.1:52500', transport: 'socket'
wait void 
*********
wait void params1 long params2 int 
*********
wait void params1 long 
*********
equals boolean params1 class java.lang.Object 
*********
toString class java.lang.String 
*********
hashCode int 
*********
getClass class java.lang.Class 
*********
notify void 
*********
notifyAll void 
*********

第二种情况

getName class java.lang.String 
*********
setName void params1 class java.lang.String 
*********
color void params1 int 
*********
setSex void params1 int 
*********
getSex int 
*********

我将所有方法名、返回值、参数类型一起打印出来了,这样大家看的比较直观

我一样先setName 再 getName 加以验证

Method method1=class_1.getDeclaredMethod("setName", String.class);
method1.invoke(person, "World");
Method method2=class_1.getDeclaredMethod("getName");
String value3=method2.invoke(person).toString();

打印出来就是一个World

简单解释一下getMethod(String name, Class<?>... parameterTypes)方法中的两个参数:
name:方法名
parameterTypes:该方法的所有参数类型数组
创建method方法的时候getDeclaredMethod("setName", String.class);可以写成getDeclaredMethod("setName", new Class[] {String.class});
使用的时候同样method1.invoke(person, "World");可以写成method1.invoke(person, new Object[]{"World"});

如果是私有方法,需要加上method1.setAccessible(true);

如果是静态方法,那么我们无需传类对象就可以使用

public static void showValue() {    
    System.out.println("aaaa");
}

Method method3=class_1.getDeclaredMethod("showValue");
method3.invoke(null);

相关文章

  • [JAVA学习笔记] 反射机制

    [JAVA学习笔记] 反射机制 Java的反射通过Class类和java.lang.reflect类库实现。通过它...

  • Java中反射的用途

    Java的反射机制是Java特性之一,反射机制是构建框架技术的基础所在。灵活掌握Java反射机制,对大家以后学习框...

  • 【转】Java编程学习之反射技术及其应用

    【转】Java编程学习之反射技术及其应用 (原文链接:java编程学习之反射技术及其应用) 说明:原文中给出的代码...

  • 博客地址

    java注解-01、java注解-02、Git面试资源java反射-01、java反射-02、java反射-03为...

  • Java学习:反射

    反射 使用反射可以直接获取class字节码文件中的类型、属性、方法。 演示代码: 新建一个名为User的类作为反射...

  • Java反射机制入门

    Java反射机制入门 一、什么是反射 JAVA反射机制(The JAVA reflection mechanism...

  • java基础之反射机制,学习spring框架进阶必学!

    理解反射对学习Java框架有很大的帮助,如Spring框架的核心就是使用Java反射实现的,而且对做一些Java底...

  • java反射实例

    理解反射对学习Java框架有很大的帮助,如Spring框架的核心就是使用Java反射实现的,而且对做一些Java底...

  • 反射 — Java 高级开发必须懂的

    理解反射对学习Java框架有很大的帮助,如Spring框架的核心就是使用Java反射实现的,而且对做一些Java底...

  • Java基础之反射

    Java基础之—反射(非常重要)Java中反射机制详解Java进阶之reflection(反射机制)——反射概念与...

网友评论

    本文标题:Java反射学习

    本文链接:https://www.haomeiwen.com/subject/nkucdttx.html