Java反射机制ABC

JAVA反射机制

在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。在java中,只要给定类的名字, 那么就可以通过反射机制来获得类的所有信息:包括其modifiers、superclass、实现interfaces、fields和methods的所有信息,并可于运行时改变fields内容或唤起methods(下面的例子会逐一演示)。
Java反射机制容许程序在运行时加载、探知、使用编译期间完全未知的classes:Java可以加载一个运行时才得知名称的class,获得其完整结构。

反射是Java中一种强大的工具,能够使我们很方便的创建灵活的代码,这些代码可以再运行时装配,无需在组件之间进行源代码链接。但是反射使用不当会成本很高

优缺点

首先要搞清楚为什么要用反射机制?直接创建对象不就可以了吗,这就涉及到了动态与静态的概念

  • 静态编译:在编译时确定类型,绑定对象,即通过。
  • 动态编译:运行时确定类型,绑定对象。动态编译最大限度发挥了java的灵活性,体现了多态的应用,有以降低类之间的藕合性。

反射机制的优点:可以实现动态创建对象和编译,体现出很大的灵活性(特别是在J2EE的开发中它的灵活性就表现的十分明显)。通过反射机制我们可以获得类的各种内容,进行了反编译。对于JAVA这种先编译再运行的语言来说,反射机制可以使代码更加灵活,更加容易实现面向对象。
反射机制的缺点:对性能有影响。使用反射基本上是一种解释操作,我们可以告诉JVM,我们希望做什么并且它 满足我们的要求。这类操作总是慢于只直接执行相同的操作。

此段引自网友归纳

JAVA反射机制作用

  • 在运行时判断任意一个对象所属的类
  • 在运行时构造任意一个类的对象
  • 在运行时判段任意一个类所具有的成员变量和方法
  • 在运行时调用任一个对象的方法
  • 在运行时创建新类对象

示例

在开始示例之前,先了解下API提供的哪些函数 (参考java.lang.Class)

class 方法 含义
FieldgetField(String name) 返回一个Field对象,它反映此 Class 对象所表示的类或接口的指定公共成员字段
Field[] getFields() 返回一个包含某些 Field 对象的数组,这些对象反映此 Class 对象所表示的类或接口的所有可访问公共字段
FieldgetDeclaredField(Stringname) 返回一个 Field 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明字段
Field[] getDeclaredFields() 返回 Field 对象的一个数组,这些对象反映此 Class 对象所表示的类或接口所声明的所有字段
MethodgetMethod(String name,Class<?>… parameterTypes) 返回一个 Method 对象,它反映此 Class 对象所表示的类或接口的指定公共成员方法
Method[] getMethods() 返回一个包含某些 Method 对象的数组,这些对象反映此 Class 对象所表示的类或接口(包括那些由该类或接口声明的以及从超类和超接口继承的那些的类或接口)的公共 member 方法
MethodgetDeclaredMethod(Stringname,Class<?>… parameterTypes) 返回一个 Method 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明方法
Method[] getDeclaredMethods() 返回 Method 对象的一个数组,这些对象反映此 Class 对象表示的类或接口声明的所有方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法
Constructor<T> getConstructor(Class<?>… parameterTypes) 返回一个 Constructor 对象,它反映此 Class 对象所表示的类的指定公共构造方法
Constructor<?>[] getConstructors() 返回一个包含某些 Constructor 对象的数组,这些对象反映此 Class 对象所表示的类的所有公共构造方法
Constructor<T> getDeclaredConstructor(Class<?>… parameterTypes) 返回一个 Constructor 对象,该对象反映此 Class 对象所表示的类或接口的指定构造方法
Constructor<?>[] getDeclaredConstructors() 返回 Constructor 对象的一个数组,这些对象反映此 Class 对象表示的类声明的所有构造方法。它们是公共、保护、默认(包)访问和私有构造方法

 
更多更具体的说明可以自行深挖jdk API……

获取类的Class对象

在使用Java的反射功能时,基本首先都要获取类的Class对象,再通过Class对象获取其他的对象。

  • 调用getClass
  • 运用.class 语法
  • 运用static method Class.forName() (此方法使用频率比较高)
  • 运用primitive wrapper classes的TYPE 语法
package com.reflect.demo;

public class ParentClass {

    private String parentPrivateName;
    protected String parentProtectedName;
    public String parentPublicName;
    public String getParentPrivateName() {
        return parentPrivateName;
    }
    public void setParentPrivateName(String parentPrivateName) {
        this.parentPrivateName = parentPrivateName;
    }
    public String getParentProtectedName() {
        return parentProtectedName;
    }
    public void setParentProtectedName(String parentProtectedName) {
        this.parentProtectedName = parentProtectedName;
    }
    public String getParentPublicName() {
        return parentPublicName;
    }
    public void setParentPublicName(String parentPublicName) {
        this.parentPublicName = parentPublicName;
    }


    private void parentPrivateMethod() {

    }
    protected void parentProtectedMethod() {

    }
    public void parentPublicMethod() {

    }
}
package com.reflect.demo;

public class ShowMe extends ParentClass{
    private String privateName;
    protected String protectedName;
    public String publicName;

    public void methodTest(){
        System.out.println("methodTest void");
    }
    public void methodTest(String name,String firstName){
        System.out.println("name:"+name+"firstName:"+firstName);
    }

    public String methodReturn(String name,String firstName){
        System.out.println("methodReturn returnString");
        return "methodReturn";
    }

    public String getPrivateName() {
        return privateName;
    }

    public void setPrivateName(String privateName) {
        this.privateName = privateName;
    }

    public String getProtectedName() {
        return protectedName;
    }

    public void setProtectedName(String protectedName) {
        this.protectedName = protectedName;
    }

    public String getPublicName() {
        return publicName;
    }

    public void setPublicName(String publicName) {
        this.publicName = publicName;
    }

    private void privateMethod() {

    }
    protected void protectedMethod() {

    }
    public void publicMethod() {

    }
    public ShowMe() {
        super();
    }

    public ShowMe(String privateName, String protectedName, String publicName) {
        super();
        this.privateName = privateName;
        this.protectedName = protectedName;
        this.publicName = publicName;
    }
}
package com.reflect.demo.main;

import com.reflect.demo.ShowMe;

public class GetClassMain {

    public static void main(String[] args) throws InstantiationException, IllegalAccessException, ClassNotFoundException {
        ShowMe showMe = new ShowMe();
        System.out.println(showMe.getClass().getName());
        System.out.println(ShowMe.class.getName());
        System.out.println(Class.forName("com.reflect.demo.ShowMe").getName());
        System.out.println(Boolean.TYPE);
    }
}

输出结果:

com.reflect.demo.ShowMe
com.reflect.demo.ShowMe
com.reflect.demo.ShowMe
boolean

获取类的Fields

重写main函数

package com.reflect.demo.main;

import java.lang.reflect.Field;

import com.reflect.demo.ShowMe;

public class GetClassMain {

    public static void main(String[] args) throws InstantiationException, IllegalAccessException, ClassNotFoundException {
        //获取fileds
        Class<?> showMe_GetFileds = ShowMe.class;  

        Field[] fields = showMe_GetFileds.getFields();  
        for (Field field : fields)  
        {  
            System.out.println("getFields:"+field);  
        }  

        System.out.println();  

        // 使用getDeclaredFields获取属性  
        fields = showMe_GetFileds.getDeclaredFields();  
        for (Field field : fields)  
        {  
            System.out.println("getDeclaredFields:"+field);  
        }  
    }
}

输出结果:

getFields:public java.lang.String com.reflect.demo.ShowMe.publicName
getFields:public java.lang.String com.reflect.demo.ParentClass.parentPublicName

getDeclaredFields:private java.lang.String com.reflect.demo.ShowMe.privateName
getDeclaredFields:protected java.lang.String com.reflect.demo.ShowMe.protectedName
getDeclaredFields:public java.lang.String com.reflect.demo.ShowMe.publicName

getFields和getDeclaredFields区别:
getFields返回的是申明为public的属性,包括父类中定义
getDeclaredFields返回的是指定类定义的所有定义的属性,不包括父类的。

获取类的Method

重写测试main函数

package com.reflect.demo.main;

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

import com.reflect.demo.ShowMe;

public class GetClassMain {

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

        //获取method
        Class<?> showMe_GetMethods = ShowMe.class;  
        Method[] methods = showMe_GetMethods.getMethods();  
        for (Method method : methods)  
        {  
            System.out.println("getMethods:"+method);  
        }  
        System.out.println();  
        // 使用getDeclaredMethods获取函数   
        methods = showMe_GetMethods.getDeclaredMethods();  
        for (Method method : methods)  
        {  
            System.out.println("getDeclaredMethods:"+method);  
        }  
    }
}

输出结果:

getMethods:public java.lang.String com.reflect.demo.ShowMe.methodReturn(java.lang.String,java.lang.String)
getMethods:public void com.reflect.demo.ShowMe.methodTest()
getMethods:public void com.reflect.demo.ShowMe.methodTest(java.lang.String,java.lang.String)
getMethods:public java.lang.String com.reflect.demo.ShowMe.getPrivateName()
getMethods:public void com.reflect.demo.ShowMe.setPrivateName(java.lang.String)
getMethods:public java.lang.String com.reflect.demo.ShowMe.getProtectedName()
getMethods:public void com.reflect.demo.ShowMe.setProtectedName(java.lang.String)
getMethods:public java.lang.String com.reflect.demo.ShowMe.getPublicName()
getMethods:public void com.reflect.demo.ShowMe.setPublicName(java.lang.String)
getMethods:public void com.reflect.demo.ShowMe.publicMethod()
getMethods:public void com.reflect.demo.ShowMe.DemoIntf2Mehod()
getMethods:public void com.reflect.demo.ShowMe.DemoIntfMethod()
getMethods:public java.lang.String com.reflect.demo.ParentClass.getParentPrivateName()
getMethods:public void com.reflect.demo.ParentClass.setParentPrivateName(java.lang.String)
getMethods:public java.lang.String com.reflect.demo.ParentClass.getParentProtectedName()
getMethods:public void com.reflect.demo.ParentClass.setParentProtectedName(java.lang.String)
getMethods:public java.lang.String com.reflect.demo.ParentClass.getParentPublicName()
getMethods:public void com.reflect.demo.ParentClass.setParentPublicName(java.lang.String)
getMethods:public void com.reflect.demo.ParentClass.parentPublicMethod()
getMethods:public final void java.lang.Object.wait() throws java.lang.InterruptedException
getMethods:public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
getMethods:public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
getMethods:public boolean java.lang.Object.equals(java.lang.Object)
getMethods:public java.lang.String java.lang.Object.toString()
getMethods:public native int java.lang.Object.hashCode()
getMethods:public final native java.lang.Class java.lang.Object.getClass()
getMethods:public final native void java.lang.Object.notify()
getMethods:public final native void java.lang.Object.notifyAll()

getDeclaredMethods:public java.lang.String com.reflect.demo.ShowMe.methodReturn(java.lang.String,java.lang.String)
getDeclaredMethods:public void com.reflect.demo.ShowMe.methodTest()
getDeclaredMethods:public void com.reflect.demo.ShowMe.methodTest(java.lang.String,java.lang.String)
getDeclaredMethods:public java.lang.String com.reflect.demo.ShowMe.getPrivateName()
getDeclaredMethods:public void com.reflect.demo.ShowMe.setPrivateName(java.lang.String)
getDeclaredMethods:public java.lang.String com.reflect.demo.ShowMe.getProtectedName()
getDeclaredMethods:public void com.reflect.demo.ShowMe.setProtectedName(java.lang.String)
getDeclaredMethods:public java.lang.String com.reflect.demo.ShowMe.getPublicName()
getDeclaredMethods:public void com.reflect.demo.ShowMe.setPublicName(java.lang.String)
getDeclaredMethods:private void com.reflect.demo.ShowMe.privateMethod()
getDeclaredMethods:protected void com.reflect.demo.ShowMe.protectedMethod()
getDeclaredMethods:public void com.reflect.demo.ShowMe.publicMethod()
getDeclaredMethods:public void com.reflect.demo.ShowMe.DemoIntf2Mehod()
getDeclaredMethods:public void com.reflect.demo.ShowMe.DemoIntfMethod()

获取类的Constructor

package com.reflect.demo.main;

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

import com.reflect.demo.ShowMe;

public class GetClassMain {

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

        Class<?> showMe_GetConstructor = ShowMe.class;  
        Constructor<?>[] constructors = showMe_GetConstructor.getConstructors();  
        for (Constructor<?> constructor : constructors)  
        {  
            System.out.println("getConstructors:"+constructor);  
        }  

        System.out.println();  

        // 使用getDeclaredConstructors获取构造器     
        constructors = showMe_GetConstructor.getDeclaredConstructors();  
        for (Constructor<?> constructor : constructors)  
        {  
            System.out.println("getDeclaredConstructors:"+constructor);  
        }  


    }
}

输出结果:

getConstructors:public com.reflect.demo.ShowMe(java.lang.String,java.lang.String,java.lang.String)
getConstructors:public com.reflect.demo.ShowMe()

getDeclaredConstructors:public com.reflect.demo.ShowMe(java.lang.String,java.lang.String,java.lang.String)
getDeclaredConstructors:public com.reflect.demo.ShowMe()

实例化类对象

实例化对象的集中方法、其中使用newInstance时,需要注意:默认是调用无参构造函数,若显式调用有参构造函数,需要在类中定义,以免报错。

package com.reflect.demo.main;

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

import com.reflect.demo.ShowMe;

public class GetClassMain {

    public static void main(String[] args) throws InstantiationException, IllegalAccessException, ClassNotFoundException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException {
        Class<?> showMeFirst = null;
        Class<?> showMeSecond = null;
        Class<?> showMeThird = null;

        ShowMe showMeInstanceF= null;
        ShowMe showMeInstanceS= null;
        ShowMe showMeInstanceT= null;
        ShowMe showMeInstanceDefaultConstruct= null;
        ShowMe showMeInstanceConstruct= null;


        showMeFirst=Class.forName("com.reflect.demo.ShowMe");
        showMeSecond=new ShowMe().getClass();
        showMeThird=ShowMe.class;

        showMeInstanceF=(ShowMe)showMeFirst.newInstance();
        showMeInstanceS=(ShowMe)showMeSecond.newInstance();
        showMeInstanceT=(ShowMe)showMeThird.newInstance();

        Constructor<?> constructorDefault = showMeThird.getConstructor();
        showMeInstanceDefaultConstruct = (ShowMe)constructorDefault.newInstance();
        Constructor<?> constructor = showMeThird.getConstructor(String.class,String.class,String.class);
        showMeInstanceConstruct=(ShowMe)constructor.newInstance("lilei","hanmeimei","poly");

        showMeInstanceF.methodReturn(null, null);
        showMeInstanceS.methodReturn(null, null);
        showMeInstanceT.methodReturn(null, null);
        showMeInstanceDefaultConstruct.methodReturn(null, null);
        showMeInstanceConstruct.methodReturn(null, null);
    }
}

输出结果:

methodReturn returnString
methodReturn returnString
methodReturn returnString
methodReturn returnString
methodReturn returnString

返回一个类的实现接口

package com.reflect.demo.main;

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

import com.reflect.demo.ShowMe;

public class GetClassMain {

    public static void main(String[] args) throws InstantiationException, IllegalAccessException, ClassNotFoundException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException {
        Class<?> showMe_GetIntfs=Class.forName("com.reflect.demo.ShowMe");
        Class<?> intes[]=showMe_GetIntfs.getInterfaces();
        for (int i = 0; i < intes.length; i++) {
             System.out.println("Interface:   "+intes[i].getName());
        }
    }
}

输出结果:

Interface:   com.reflect.demo.DemoIntf
Interface:   com.reflect.demo.DemoIntf2

获取父类

package com.reflect.demo.main;

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

import com.reflect.demo.ShowMe;

public class GetClassMain {

    public static void main(String[] args) throws InstantiationException, IllegalAccessException, ClassNotFoundException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException {
        Class<?> showMe_GetParent=Class.forName("com.reflect.demo.ShowMe");
        Class<?> parent=showMe_GetParent.getSuperclass();
        System.out.println("Parent:   "+parent.getName());
    }
}

输出结果:

Parent:   com.reflect.demo.ParentClass

调用类中的方法

package com.reflect.demo.main;

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

import com.reflect.demo.ShowMe;

public class GetClassMain {

    public static void main(String[] args) throws InstantiationException, IllegalAccessException, ClassNotFoundException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException {
        Class<?> showMe_Invoke = Class.forName("com.reflect.demo.ShowMe");
        Method method = showMe_Invoke.getMethod("methodTest");
        method.invoke(showMe_Invoke.newInstance());

        method = showMe_Invoke.getMethod("methodTest", String.class, String.class);
        method.invoke(showMe_Invoke.newInstance(), "xxx", "yyy");
    }
}

输出结果:

methodTest void
name:xxxfirstName:yyy

调用setter和getter

package com.reflect.demo.main;

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

import com.reflect.demo.ShowMe;

public class GetClassMain {

    public static void main(String[] args) throws InstantiationException, IllegalAccessException, ClassNotFoundException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException {
        Class<?> showMe_getterSetter = Class.forName("com.reflect.demo.ShowMe");
        Object object = showMe_getterSetter.newInstance();

        Method method_set = object.getClass().getMethod("set" + "PrivateName",String.class);
        method_set.invoke(object, "uuuuuuuuuuuuuuuuu love");
        Method method_get = object.getClass().getMethod("get" + "PrivateName");
        System.out.println(method_get.invoke(object));
    }
}

输出结果:

uuuuuuuuuuuuuuuuu love

操作属性

package com.reflect.demo.main;

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

import com.reflect.demo.ShowMe;

public class GetClassMain {

    public static void main(String[] args) throws InstantiationException, IllegalAccessException, ClassNotFoundException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException {
        Class<?> showMe_field = Class.forName("com.reflect.demo.ShowMe");
        Object object_field = showMe_field.newInstance();

        Field field = showMe_field.getDeclaredField("privateName");
        field.setAccessible(true);
        field.set(object_field, "show show me!");
        System.out.println(field.get(object_field));
    }
}

输出结果:

show show me!

猜你喜欢

转载自blog.csdn.net/yue530tomtom/article/details/79486669
今日推荐