java反射

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{}
}

复制代码

复制代码

@Deprecatedpublic 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 reflectionClass<?> 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 arraysClass<?> booleanClass = boolean.class;
System.out.println(booleanClass.getCanonicalName()); // prints booleanClass<?> cDouble = Double.TYPE;
System.out.println(cDouble.getCanonicalName()); // prints doubleClass<?> 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 ConcreteClassClass<?>[] 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, ObjectSystem.out.println(Arrays.toString(publicMethods));

获取所有public Constructors

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

获取所有public Fields

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

//Get All public fieldsField[] publicFields = Class.forName("com.journaldev.reflection.ConcreteClass").getFields();//prints public fields of ConcreteClass, it's superclass and super interfacesSystem.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 5field.setInt(obj, 10); //setting field value to 10 in objectSystem.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 voidSystem.out.println(method.getReturnType());//get method modifiersSystem.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 methodMethod 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 parametersSystem.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 parametersSystem.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);

复制代码


上一篇: java十宗罪

下一篇: Java——永存、曲折、低谷、重生!

分享到: 更多