------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------
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)
-------------------
字段: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
无参构造方法对象!!!
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是枚举
}
}