Java反射机制


Java反射概念:

反射(Reflection) 是Java 程序开发语言的特征之一,它允许运行中的Java 程序对自身进行检查,或者说“自审”,并能直接操作程序的内部属性。


反射的优缺点:

优点:可以实现动态创建对象和编译,有很大的灵活性。

缺点:反射包括了一些动态类型,所以JVM无法对这些代码进行优化。因此,反射操作的效率要比那些非反射操作低得多。反射虽好,谨慎使用!


反射中主要的类:



Class类:代表一个类。


Field 类:代表类的成员变量(成员变量也称为类的属性)。


Method类:代表类的方法。


Constructor 类:代表类的构造方法。


Array类:提供了动态创建数组,以及访问数组的元素的静态方法。




Class类主要方法:


getName():获得类的完整名字。



getFields():获得类的public类型的属性。



getDeclaredFields():获得类的所有属性。



getMethods():获得类的public类型的方法。



getDeclaredMethods():获得类的所有方法。



getMethod(String name, Class[] parameterTypes):获得类的特定方法,name参数指定方法的名字,parameterTypes 参数指定方法的参数类型。



getConstructors():获得类的public类型的构造方法。



getConstructor(Class[] parameterTypes):获得类的特定构造方法,parameterTypes 参数指定构造方法的参数类型。



newInstance():通过类的不带参数的构造方法创建这个类的一个对象






如:



package guan.com.reflect;

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

class guan {
	private int age;
	private String name;
	private String sex;
	public int number;
	guan(String name){

	}
	public void show(){
		System.out.println("guan show");
	}
	public void print(){};
	private void tes(){};


}
public class test {
	public static void main(String args[]) throws Exception {
		//guan g = new guan();


		Class<guan> gu = guan.class;
		System.out.println(gu.getName());//获得类的完整名字
		System.out.println("-------------------");

		Field[] f = gu.getFields();//获得类的public类型的属性
		for(Field field:f){
			System.out.println("字段:"+field);
		}
		System.out.println("-------------------");

		f = gu.getDeclaredFields();
		for(Field field:f){
			System.out.println("全部字段:"+field);//:获得类的所有属性
		}
		System.out.println("-------------------");

		Method[] m = gu.getMethods();//获得类的public类型的方法
		for (Method method : m) {
			System.out.println("public类型的方法:"+method);
		}
		System.out.println("-------------------");

		m = gu.getDeclaredMethods();//获得类的所有方法
		for (Method method : m) {
			System.out.println("全部方法:"+method);
		}
		System.out.println("-------------------");

		Method me = gu.getDeclaredMethod("show");//获得类的特定方法,name参数指定方法的名字,
		System.out.println("show "+me);
		System.out.println("-------------------");

		Constructor[] con = gu.getConstructors();//前面的修饰符必须是public才可以在这个方法下获取到
		for (Constructor cons : con) {
			System.out.println("c.getConstructors()"+cons);//如果上面的某构造器public去掉,则显示不出
		}
		System.out.println("-------------------");

		con = gu.getDeclaredConstructors();//现在想获得不受public影响的,getDeclaredConstructors(),暴力反射
		for (Constructor cons : con) {
			System.out.println("c.getDeclaredConstructors()"+cons);

		}
	}
}






输出:



guan.com.reflect.guan
-------------------
字段:public int guan.com.reflect.guan.number
-------------------
全部字段:private int guan.com.reflect.guan.age
全部字段:private java.lang.String guan.com.reflect.guan.name
全部字段:private java.lang.String guan.com.reflect.guan.sex
全部字段:public int guan.com.reflect.guan.number
-------------------
public类型的方法:public void guan.com.reflect.guan.print()
public类型的方法:public void guan.com.reflect.guan.show()
public类型的方法:public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
public类型的方法:public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
public类型的方法:public final void java.lang.Object.wait() throws java.lang.InterruptedException
public类型的方法:public boolean java.lang.Object.equals(java.lang.Object)
public类型的方法:public java.lang.String java.lang.Object.toString()
public类型的方法:public native int java.lang.Object.hashCode()
public类型的方法:public final native java.lang.Class java.lang.Object.getClass()
public类型的方法:public final native void java.lang.Object.notify()
public类型的方法:public final native void java.lang.Object.notifyAll()
-------------------
全部方法:public void guan.com.reflect.guan.print()
全部方法:public void guan.com.reflect.guan.show()
全部方法:private void guan.com.reflect.guan.tes()
-------------------
show public void guan.com.reflect.guan.show()
-------------------
-------------------
c.getDeclaredConstructors()guan.com.reflect.guan(java.lang.String)












利用反射创建对象:



如:



package guan.com.reflect;

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

class guan{
	public String name;
	private int age;
	public guan(){	
	}
	private guan(String name){
	}
	public String toString() {
		return "对象!!!";
	}
	public String show(String n){//用反射的方法来调用正常的方法
		return name+",您好!";
	}
	
	private void privateshow(){//用反射来实现对私有化方法的调用
		System.out.println("privateshow");
	}
	public static void staticshow(){
		System.out.println("staticshow");
	}


	
}

public class test {
	public static void main(String[] args) throws Exception {
		Class<guan> g = guan.class;
		//System.out.println(c.newInstance());;//证明利用无参的可以
		
		先获得需要被调用的构造器(private 修饰的构造方法)
		Constructor<guan> con = g.getDeclaredConstructor();//调用默认的,什么都不要写
		System.out.println(con);//private junereflect624.Per()
		//私有的成员是受保护的,不能直接访问
		//若要访问私有的成员,得先申请一下
		con.setAccessible(true);//允许访问
		guan p = con.newInstance();//成功,通过私有的受保护的构造方法创建了对象
		System.out.println("无参构造方法"+p);
		
		con = g.getDeclaredConstructor(String.class);
		System.out.println(con);//private junereflect624.Per(java.lang.String)
			
		con.setAccessible(true);//允许访问
		p = con.newInstance("liuzhao");//成功,通过私有的受保护的构造方法创建了对象
		System.out.println("String构造方法"+p);
		
		
		//想要通过反射来调用Dept中的方法
				Class<guan> c = guan.class;
				Method m = c.getMethod("show", String.class);
				Object o = m.invoke(c.newInstance(), "黑马程序员");
				System.out.println(o);
				
				//私有化的方法
				m = c.getDeclaredMethod("privateshow");//无参方法
				m.setAccessible(true);
				o = m.invoke(c.newInstance());
				
				//静态方法的调用
				m = c.getMethod("staticshow");
				m.invoke(null);//staticshow为静态方法,不需创建对象,所以这里会是null

	}
}






输出:



public guan.com.reflect.guan()
无参构造方法对象!!!
private guan.com.reflect.guan(java.lang.String)
String构造方法对象!!!
null,您好!
privateshow
staticshow








反射总结:

对于方法,字段,构造方法之类用类获取记住四个:获取全部,获取特定,暴力获取全部,暴力获取特定!

反射可以破坏单例设计模式

但是!!!


package guan.com.reflect;

import java.lang.reflect.Constructor;

enum Color{
	RED,BLUE,GREEN;
	private Color(){
	}
}

public class test {
	public static void main(String[] args) throws Exception {
		Class<Color> c = Color.class;
		
		Constructor<Color> con = c.getDeclaredConstructor();//(错误在这一行发生,就是说对枚举而言这种方法连构造器都获得不了,)编译可以通过,但是运行就通不过了!
		Color co = (Color) con.newInstance();
		System.out.println(co);//失败,证明对枚举而言不行,所以枚举的单例模式更加安全
		System.out.println(c.isEnum());//true是枚举
	}
}