java反射

JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

一般情况下,我们不应该在正常编程中使用反射,因为存在以下缺点:

  1. 性能低-因为java反射动态地解析类型,它涉及处理像扫描类路径找到要加载的类,导致性能降低。
  2. 安全限制-反射需要运行时权限,可能不适用于在安全管理器下运行的系统。这可能会导致应用程序在运行时由于安全管理器而失败。
  3. 安全问题-使用反射,我们可以访问我们不应该访问的部分代码,例如,我们可以访问类的私有字段并更改它的值。这可能是一个严重的安全威胁,并导致您的应用程序的行为异常。
  4. 高维护-反射代码很难理解和调试,在编译时也无法找到代码的任何问题,因为类可能不可用,使得它不太灵活和难以维护。

 

API简介
— java.lang.Class; 代表一个类

  — java.lang.reflect.Constructor; 代表类的构造方法

  — java.lang.reflect.Field; 代表类的成员变量(成员变量也称为类的属性)

  — java.lang.reflect.Method;  代表类的方法

  — java.lang.reflect.Array;  提供了动态创建数组,以及访问数组的元素的静态方法

定义类

public interface BaseInterface {
    
    public int interfaceInt=0;
    
    void method1();
    
    int method2(String str);
}
public class BaseClass {

    public int baseInt;
    
    private static void method3(){
        System.out.println("Method3");
    }
    
    public int method4(){
        System.out.println("Method4");
        return 0;
    }
    
    public static int method5(){
        System.out.println("Method5");
        return 0;
    }
    
    void method6(){
        System.out.println("Method6");
    }
    
    // inner public class
    public class BaseClassInnerClass{}
        
    //member public enum
    public enum BaseClassMemberEnum{}
}
@Deprecated
public class ConcreteClass extends BaseClass implements BaseInterface {

    public int publicInt;
    private String privateString="private string";
    protected boolean protectedBoolean;
    Object defaultObject;
    
    public ConcreteClass(int i){
        this.publicInt=i;
    }

    @Override
    public void method1() {
        System.out.println("Method1 impl.");
    }

    @Override
    public int method2(String str) {
        System.out.println("Method2 impl.");
        return 0;
    }
    
    @Override
    public int method4(){
        System.out.println("Method4 overriden.");
        return 0;
    }
    
    public int method5(int i){
        System.out.println("Method4 overriden.");
        return 0;
    }
    
    // inner classes
    public class ConcreteClassPublicClass{}
    private class ConcreteClassPrivateClass{}
    protected class ConcreteClassProtectedClass{}
    class ConcreteClassDefaultClass{}
    
    //member enum
    enum ConcreteClassDefaultEnum{}
    public enum ConcreteClassPublicEnum{}
    
    //member interface
    public interface ConcreteClassPublicInterface{}

}

 

获取类对象

可以使用三个方法来获得对象的Class - 通过静态变量类,使用对象的getClass()方法和java.lang.Class.forName(String fullyClassifiedClassName)。

1)、使用Class类的forName(String className)静态方法。改方法需要传入字符串参数,改字符串参数的值是某个类的全限定类名(必须添加完整的包名)。

Class.forName("java.lang.String");

2)、调用某个类的class属性来获取该类对应的class对象

String.class

3)、调用某个对象的getClass方法。

String s = "aa";
Class<?> clazz = s.getClass();

对于基本类型和数组,我们可以使用静态变量类。包装器类提供另一个静态变量TYPE来获取类。

// Get Class using reflection
Class<?> concreteClass = ConcreteClass.class;
concreteClass = new ConcreteClass(5).getClass();
try {
    // below method is used most of the times in frameworks like JUnit
    //Spring dependency injection, Tomcat web container
    //Eclipse auto completion of method names, hibernate, Struts2 etc.
    //because ConcreteClass is not available at compile time
    concreteClass = Class.forName("com.journaldev.reflection.ConcreteClass");
} catch (ClassNotFoundException e) {
    e.printStackTrace();
}
System.out.println(concreteClass.getCanonicalName()); // prints com.journaldev.reflection.ConcreteClass

//for primitive types, wrapper classes and arrays
Class<?> booleanClass = boolean.class;
System.out.println(booleanClass.getCanonicalName()); // prints boolean

Class<?> cDouble = Double.TYPE;
System.out.println(cDouble.getCanonicalName()); // prints double

Class<?> cDoubleArray = Class.forName("[D");
System.out.println(cDoubleArray.getCanonicalName()); //prints double[]

Class<?> twoDStringArray = String[][].class;
System.out.println(twoDStringArray.getCanonicalName()); // prints java.lang.String[][]

获取Super Class

如果此类表示Object类,接口,原始类型或void,则getSuperclass() 返回null。

Class<?> superClass = Class.forName("com.journaldev.reflection.ConcreteClass").getSuperclass();
System.out.println(superClass); // prints "class com.journaldev.reflection.BaseClass"
System.out.println(Object.class.getSuperclass()); // prints "null"
System.out.println(String[][].class.getSuperclass());// prints "class java.lang.Object"

获取Declared类

getDeclaredClasses()方法返回一个Class对象数组,反射所有被声明为由此Class对象表示的类的成员的类和接口。返回的数组不包括在继承的类和接口中声明的类。

//getting all of the classes, interfaces, and enums that are explicitly declared in ConcreteClass
Class<?>[] explicitClasses = Class.forName("com.journaldev.reflection.ConcreteClass").getDeclaredClasses();
//prints [class com.journaldev.reflection.ConcreteClass$ConcreteClassDefaultClass, 
//class com.journaldev.reflection.ConcreteClass$ConcreteClassDefaultEnum, 
//class com.journaldev.reflection.ConcreteClass$ConcreteClassPrivateClass, 
//class com.journaldev.reflection.ConcreteClass$ConcreteClassProtectedClass, 
//class com.journaldev.reflection.ConcreteClass$ConcreteClassPublicClass, 
//class com.journaldev.reflection.ConcreteClass$ConcreteClassPublicEnum, 
//interface com.journaldev.reflection.ConcreteClass$ConcreteClassPublicInterface]
System.out.println(Arrays.toString(explicitClasses));

获取Package名字

//prints "com.journaldev.reflection"
System.out.println(Class.forName("com.journaldev.reflection.BaseInterface").getPackage().getName());

获取类的Modifiers

System.out.println(Modifier.toString(concreteClass.getModifiers())); //prints "public"
//prints "public abstract interface"
System.out.println(Modifier.toString(Class.forName("com.journaldev.reflection.BaseInterface").getModifiers())); 

获取Type Parameters

//Get Type parameters (generics)
TypeVariable<?>[] typeParameters = Class.forName("java.util.HashMap").getTypeParameters();
for(TypeVariable<?> t : typeParameters)
System.out.print(t.getName()+",");

获取Implemented Interfaces

Type[] interfaces = Class.forName("java.util.HashMap").getGenericInterfaces();
//prints "[java.util.Map<K, V>, interface java.lang.Cloneable, interface java.io.Serializable]"
System.out.println(Arrays.toString(interfaces));
//prints "[interface java.util.Map, interface java.lang.Cloneable, interface java.io.Serializable]"
System.out.println(Arrays.toString(Class.forName("java.util.HashMap").getInterfaces()));

获取所有的public Methods

getMethods()方法返回类的公共方法数组,包括它的超类和超级接口的公共方法。

Method[] publicMethods = Class.forName("com.journaldev.reflection.ConcreteClass").getMethods();
//prints public methods of ConcreteClass, BaseClass, Object
System.out.println(Arrays.toString(publicMethods));

获取所有public Constructors

//Get All public constructors
Constructor<?>[] publicConstructors = Class.forName("com.journaldev.reflection.ConcreteClass").getConstructors();
//prints public constructors of ConcreteClass
System.out.println(Arrays.toString(publicConstructors));

获取所有public Fields

getFields()方法返回类的公共字段数组,包括它的超级类和超级接口的公共字段。

//Get All public fields
Field[] publicFields = Class.forName("com.journaldev.reflection.ConcreteClass").getFields();
//prints public fields of ConcreteClass, it's superclass and super interfaces
System.out.println(Arrays.toString(publicFields));

获取所有Annotations

java.lang.annotation.Annotation[] annotations = Class.forName("com.journaldev.reflection.ConcreteClass").getAnnotations();
//prints [@java.lang.Deprecated()]
System.out.println(Arrays.toString(annotations));

获取指定的Public Field

 getField() 方法在指定的类引用中查找字段,然后在超级接口中,然后在超类中。

Field field = Class.forName("com.journaldev.reflection.ConcreteClass").getField("interfaceInt");

通过属性获取类

try {
    Field field = Class.forName("com.journaldev.reflection.ConcreteClass").getField("interfaceInt");
    Class<?> fieldClass = field.getDeclaringClass();
    System.out.println(fieldClass.getCanonicalName()); //prints com.journaldev.reflection.BaseInterface
} catch (NoSuchFieldException | SecurityException e) {
    e.printStackTrace();
}

获取Field Type

Field field = Class.forName("com.journaldev.reflection.ConcreteClass").getField("publicInt");
Class<?> fieldType = field.getType();
System.out.println(fieldType.getCanonicalName()); //prints int    

Get/Set Public Field Value

Field field = Class.forName("com.journaldev.reflection.ConcreteClass").getField("publicInt");
ConcreteClass obj = new ConcreteClass(5);
System.out.println(field.get(obj)); //prints 5
field.setInt(obj, 10); //setting field value to 10 in object
System.out.println(field.get(obj)); //prints 10

获取指定的Public Method

Method method = Class.forName("java.util.HashMap").getMethod("put", Object.class, Object.class);
//get method parameter types, prints "[class java.lang.Object, class java.lang.Object]"
System.out.println(Arrays.toString(method.getParameterTypes()));
//get method return type, return "class java.lang.Object", class reference for void
System.out.println(method.getReturnType());
//get method modifiers
System.out.println(Modifier.toString(method.getModifiers())); //prints "public"

调用Public Method

如果方法是静态的,我们可以传递NULL作为对象参数。

Method method = Class.forName("java.util.HashMap").getMethod("put", Object.class, Object.class);
Map<String, String> hm = new HashMap<>();
method.invoke(hm, "key", "value");
System.out.println(hm); // prints {key=value}

调用Private Methods

//invoking private method
Method method = Class.forName("com.journaldev.reflection.BaseClass").getDeclaredMethod("method3", null);
method.setAccessible(true);
method.invoke(null, null); //prints "Method3"

获取指定的Public Constructor

Constructor<?> constructor = Class.forName("com.journaldev.reflection.ConcreteClass").getConstructor(int.class);
//getting constructor parameters
System.out.println(Arrays.toString(constructor.getParameterTypes())); // prints "[int]"
        
Constructor<?> hashMapConstructor = Class.forName("java.util.HashMap").getConstructor(null);
System.out.println(Arrays.toString(hashMapConstructor.getParameterTypes())); // prints "[]"

实例化对象使用Constructor

Constructor<?> constructor = Class.forName("com.journaldev.reflection.ConcreteClass").getConstructor(int.class);
//getting constructor parameters
System.out.println(Arrays.toString(constructor.getParameterTypes())); // prints "[int]"
        
Object myObj = constructor.newInstance(10);
Method myObjMethod = myObj.getClass().getMethod("method1", null);
myObjMethod.invoke(myObj, null); //prints "Method1 impl."

Constructor<?> hashMapConstructor = Class.forName("java.util.HashMap").getConstructor(null);
System.out.println(Arrays.toString(hashMapConstructor.getParameterTypes())); // prints "[]"
HashMap<String,String> myMap = (HashMap<String,String>) hashMapConstructor.newInstance(null);

posted on 2016-11-22 11:59  我叫涛哥  阅读(133)  评论(0编辑  收藏  举报

导航