反射

java的反射机制

在运行过程中动态的获取信息和调用对象方法的功能称为java的反射机制。

通过反射可以获得类的属性,方法,父类,接口,包相关的信息。因为类在加载的时候,会在内存中生成一个代表这个.class文件的java.lang.Class对象,.class文件包含类的所有信息。

----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

实例

package algorithm;

import java.io.Serializable;

public class Student extends Man implements Cloneable, Serializable{

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private String str;
	
	private static double d;
    public boolean b;
    public static short s; 

	public Student(){
		
	}
	public Student(String str){
		this.str = str;
	}
	public Student(boolean b){
		this.b = b;
	}
	public Student(double d){
		this.d = d;
	}
	
	private void privateMethod(){
        System.out.println("privateMethod");
    }
    
    public String publicMethod(){
        return null;
    }
	
    public String publicMethod(String str,double d){
        return "str="+str+",double="+d;
    }
    
	public static long getSerialversionuid() {
		return serialVersionUID;
	}
	public String toString()
    {
        return "str = " + str + ", d = " + d + ", b = " + b;
    }
	
}
public class Man {
	private String man1;
	
	public int man2;

	public void hello(){
		System.out.println("hello man");
	}
	
}

----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

class和classloader

public static void main(String[] args) throws Exception{
        Class<Student> c = Student.class;
        Student[] students = new Student[2];
        System.out.println("Class.getClass():" + c.getClass()); // 获取java.lang.Class的Class对象
        System.out.println("Class.getClassLoader():" + c.getClassLoader()); // 获取类的加载器
        System.out.println("Class.getSuperclass():" + c.getSuperclass()); // 获取父类Class对象
        System.out.println("Class.getInterfaces():" + c.getInterfaces()[0] + ", " + c.getInterfaces()[1]); // 获取类的接口列表,注意返回的是一个数组
        System.out.println("ArrayClass.getClass():" + students.getClass()); // 获取该数组的Class对象            
        System.out.println("ArrayClass.getComponentType():" + students.getClass().getComponentType());//数组中对象的类型
        Student student = (Student)c.newInstance(); // 根据Class实例化出一个类实例来,默认调用无参构造方法
        System.out.println("student:"+student);//student的tostring方法
    }

结果是

Class.getClass():class java.lang.Class
Class.getClassLoader():sun.misc.Launcher$AppClassLoader@23137792
Class.getSuperclass():class algorithm.Man
Class.getInterfaces():interface java.lang.Cloneable, interface java.io.Serializable
ArrayClass.getClass():class [Lalgorithm.Student;    //数组类型的class的表现方式
ArrayClass.getComponentType():class algorithm.Student
student:null
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

package

public static void main(String[] args) throws Exception{
        Class<Student> c = Student.class;
        Package p = c.getPackage();
        System.out.println("Package.toString():" + p.toString()); //toString()
        System.out.println("Package.getName():" + p.getName());     // 获取包名    
        System.out.println("Package.getImplementationTitle():" + p.getImplementationTitle()); // 获取包标题
        System.out.println("Package.getImplementationVendor():" + p.getImplementationVendor()); // 获取提供该实现的组织、供应商或公司的名称
        System.out.println("Package.getImplementationVersion():" + p.getImplementationVersion()); // 获取该实现的版本
        System.out.println("Package.isSealed():" + p.isSealed()); // 获取包是否密封的
    }

结果是

Package.toString():package algorithm
Package.getName():algorithm
Package.getImplementationTitle():null
Package.getImplementationVendor():null
Package.getImplementationVersion():null
Package.isSealed():false

----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

field

反射是直接获得属性,而不是通过get set方法

	public static void main(String[] args) throws Exception{
		
		Class<Student> c = Student.class;
		Field f1 = c.getField("b");
		Field f2 = c.getDeclaredField("d");
		Field[] fs1 = c.getFields();
		Field[] fs2 = c.getDeclaredFields();
		Student student = new Student();
		System.out.print("Class.getFields():"); // 获取类中所有public字段,顺序即public的Field定义的顺序,包括父类的
	    for (Field f : fs1)
	        System.out.print(f+"
");
	    System.out.println("-----------------------------------------------");
	    System.out.print("Class.getDeclaredFields():"); // 获取类中所有声明的字段,顺序即所有Field定义的顺序,父类的无法获取
	    for (Field f : fs2)
	        System.out.print(f + "
");
	    System.out.println("-----------------------------------------------");
	    System.out.println("Class.getField(String name):" + f1); // 根据name获取类中一个访问权限为public的字段,包括父类的
	    System.out.println("-----------------------------------------------");
	    System.out.println("Class.getDeclaredField(String name):" + f2); // 根据name获取类中声明的字段,父类的无法获取。
	    System.out.println("-----------------------------------------------");
	    System.out.println("Field.getName():" + f1.getName()); // 获取字段名
	    System.out.println("Field.getType():" + f1.getType()); // 获取该属性返回类型
	    System.out.println("Field.getModifiers():" + f1.getModifiers()); // 以整数形式返回此Field对象的Java语言修饰符,返回的值是全部修饰符对应值的和。具体对应值在下面。
	    System.out.println("Field.getBoolean():" + f1.getBoolean(student));    // 获取某个实例对象该Field的值,什么类型的Field就是getXXX(Object obj)也可以获得高精度结果。
	    System.out.println("Field.isAccessible():" + f1.isAccessible()); // 返回Field的访问权限,默认都是false。如果访问权限满足调用时的访问条件则没有什么用处。
	    f2.setAccessible(true);
	    System.out.println("Field.get():" + f2.get(student)); //获取某实例对象任意类型的field的值。要求调用该方法时对应属性的访问权限必须满足访问条件。如果不满足时,比如权限为private时,
	    //执行对应field的setAccessible(true)方法,在任何地方都可以获取值,否则抛异常。
	    System.out.println("student:"+student);
	    f1.set(student, true);
	    System.out.println("student:"+student);
	}

 结果是

Class.getFields():public boolean algorithm.Student.b
public static short algorithm.Student.s
public int algorithm.Man.man2
-----------------------------------------------
Class.getDeclaredFields():private static final long algorithm.Student.serialVersionUID
private java.lang.String algorithm.Student.str
private static double algorithm.Student.d
public boolean algorithm.Student.b
public static short algorithm.Student.s
-----------------------------------------------
Class.getField(String name):public boolean algorithm.Student.b
-----------------------------------------------
Class.getDeclaredField(String name):private static double algorithm.Student.d
-----------------------------------------------
Field.getName():b
Field.getType():boolean
Field.getModifiers():1
Field.getBoolean():false
Field.isAccessible():false
Field.get():0.0
student:str = null, d = 0.0, b = false
student:str = null, d = 0.0, b = true

 ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

constructor

public static void main(String[] args) throws Exception{
	    Class<Student> c = Student.class;
	    Constructor<?> constructor = c.getConstructor(String.class);
	    Constructor<?>[] constructors = c.getConstructors();
	    System.out.println("Class.getConstructor(String):" + constructor); // 获取指定参数列表的构造函数
	    System.out.print("Class.getConstructors():"); // 获取所有的构造函数
	    for (Constructor<?> con : constructors)
	        System.out.print(con + "
");
	    System.out.println("Constructor.getName():" + constructor.getName()); // 获取构造函数名,没什么意义,肯定是和类同名
	    System.out.println("Constructor.getModifiers():" + constructor.getModifiers()); // 获取以整数形式返回的此Constructor对象的Java语言修饰符,如public、static、final等
	    System.out.println("Constructor.isAccessible():" + constructor.isAccessible()); // 获取该Constructor的访问权限
	    System.out.println("Constructor.getParameterTypes():" + constructor.getParameterTypes()[0]); // 获取Constructor的参数类型,是个数组
	    System.out.println("Constructor.isVarArgs():" + constructor.isVarArgs()); // 获取此Constructor中是否带了可变数量的参数,即例如"String... str"类型的参数
	    Student student = (Student)constructor.newInstance("tp");//使用构造方法是constructor来实例化对象。这里的参数是String类型,如果传入int类型进去,编译时没错,但是运行时报错
	    System.out.println("student:"+student);
	}

 结果是

Class.getConstructor(String):public algorithm.Student(java.lang.String)
Class.getConstructors():public algorithm.Student(double)
public algorithm.Student(boolean)
public algorithm.Student(java.lang.String)
public algorithm.Student()
Constructor.getName():algorithm.Student
Constructor.getModifiers():1
Constructor.isAccessible():false
Constructor.getParameterTypes():class java.lang.String
Constructor.isVarArgs():false
student:str = tp, d = 0.0, b = false

  ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

 method

public static void main(String[] args) throws Exception{
		Class<Student> c = Student.class;
		Student student = new Student();
		Method md0 = c.getMethod("publicMethod", String.class, double.class);
	    Method md1 = c.getDeclaredMethod("privateMethod", new Class[0]);//对于没有参数的方法就这么写。
	    Method[] mds0 = c.getMethods();
	    Method[] mds1 = c.getDeclaredMethods();
	    System.out.println("Method.getMethod():" + md0); // 根据方法名和参数列表获取指定的public方法,继承的方法也可以。
	    System.out.println("Method.getDeclaredMethod():" + md1); // 根据方法名和参数列表获取指定的任意访问权限的方法,继承的方法不可以获取
	    System.out.println("-----------------------------------------------");
	    System.out.print("Method.getMethods():"); // 获取此类包括其父类中所有的public方法
	    for (Method m : mds0)
	        System.out.print(m + "
");
	    System.out.println("-----------------------------------------------");
	    System.out.print("Method.getDeclaredMethods():"); // 返回此类中所有的方法(无访问权限限制),继承的方法没有
	    for (Method m : mds1)
	        System.out.print(m + "
");
	    System.out.println("-----------------------------------------------");
	    System.out.println("Method.getName():" + md0.getName()); // 获取方法的名字
	    System.out.println("Method.isAccessible():" + md0.isAccessible()); // 获取方法的访问属性
	    System.out.println("Method.isVarArgs():" + md0.isVarArgs()); // 获取方法是否带有可变数量的参数
	    System.out.println("Method.getReturnType():" + md0.getReturnType()); // 获取方法的返回类型
	    System.out.println("Method.getParameterTypes():" + md0.getParameterTypes()[0] + ", " + md0.getParameterTypes()[1]); // 获取方法的参数类型,数组形式,注意一下和下面的方法的区别
	    System.out.println("Method.getGenericParameterTypes():" + md0.getGenericParameterTypes()[0] + ", " + md0.getGenericParameterTypes()[1]); // 获取方法的参数化(带泛型)类型,数组形式
	    System.out.println(md0.invoke(student, "tp", 2.2));
	}

 结果是

 Method.getMethod():public java.lang.String algorithm.Student.publicMethod(java.lang.String,double)
Method.getDeclaredMethod():private void algorithm.Student.privateMethod()
-----------------------------------------------
Method.getMethods():public java.lang.String algorithm.Student.publicMethod(java.lang.String,double)
public java.lang.String algorithm.Student.publicMethod()
public static long algorithm.Student.getSerialversionuid()
public java.lang.String algorithm.Student.toString()
public void algorithm.Man.hello()
public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
public final void java.lang.Object.wait() throws java.lang.InterruptedException
public boolean java.lang.Object.equals(java.lang.Object)
public native int java.lang.Object.hashCode()
public final native java.lang.Class java.lang.Object.getClass()
public final native void java.lang.Object.notify()
public final native void java.lang.Object.notifyAll()
-----------------------------------------------
Method.getDeclaredMethods():public java.lang.String algorithm.Student.publicMethod(java.lang.String,double)
public java.lang.String algorithm.Student.publicMethod()
private void algorithm.Student.privateMethod()
public static long algorithm.Student.getSerialversionuid()
public java.lang.String algorithm.Student.toString()
-----------------------------------------------
Method.getName():publicMethod
Method.isAccessible():false
Method.isVarArgs():false
Method.getReturnType():class java.lang.String
Method.getParameterTypes():class java.lang.String, double
Method.getGenericParameterTypes():class java.lang.String, double
str=tp,double=2.2
student:str = null, d = 0.0, b = false

  ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

getModifiers()方法的枚举

Field、Constructor、Method中都有getModifiers()方法,返回的是表示此对象的Java语言修饰符,详细看下每个修饰符对应的枚举值:

修饰符 枚举值
public 1
private 2
protected 4
static 8
final 16
synchronized 32
volatile 64
transient 128
native 256
interface 512
abstract 1024
strict

2048

getModifiers()方法是把所有的权限值加上的和。比如public static final synchronized,结果是1+8+16+32=57。每一个修饰符的值对应12位二进制的每一个位置,所以如果给出一个权限值,把它转换为二进制,那个位置上有值,就对应有哪个权限。

参考借鉴http://www.cnblogs.com/xrq730/p/4862111.html

原文地址:https://www.cnblogs.com/tp123/p/6386705.html