一.概念
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。
JAVA反射(放射)机制:“程序运行时,允许改变程序结构或变量类型,这种语言称为动态语言”。从这个观点看,Perl,Python,Ruby是动态语言,C++,Java,C#不是动态语言。但是JAVA有着一个非常突出的动态相关机制:Reflection,用在Java身上指的是我们可以于运行时加载、探知、使用编译期间完全未知的classes。换句话说,Java程序可以加载一个运行时才得知名称的class,获悉其完整构造(但不包括methods定义),并生成其对象实体、或对其fields设值、或唤起其methods。
二.Class类的使用
在面向对象的世界中万事万物皆对象,在java中除了普通数据(但有封装类)和静态类(属于类)不是对象外 其它都为对象。
那么类是对象吗?是谁的对象呢?类是对象,是java.lang.class的类。
反射机制获取类的3中方法
首先我们可以看看class的源代码,会发现这行代码
私有的构造方法,只有java虚拟机才能创建对象 所以我们不可以通过new 来创建对象
但是还有三种其它的方法可以创建对象
package reflect; /** * @author scx *Class类的使用 */ public class Main { public static void main(String[] args) { Fool fool=new Fool(); //第一种方式 任何一个类都有一个隐含的静态成员变量class Class c1=Fool.class; //第二种方式 可以通过类的对象getClass方法 Class c2=fool.getClass(); //第三种方式 通过完整的包名和类名 Class c3=null; try { c3=Class.forName("reflect.Fool"); } catch (ClassNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } /* * c1,c2,c3代表了Fool类的类类型 是class的实例对象 * 这个对象我们称为该类的类类型 */ System.out.println("c1="+c1); System.out.println("c2="+c2); System.out.println("c3="+c3); } } //Fool 是java.lang.class的对象 class Fool{}
运行结果
c1=class reflect.Fool
c2=class reflect.Fool
c3=class reflect.Fool
三.创建对象 newInstance
try { Fool fool2=(Fool) c1.newInstance(); } catch (InstantiationException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); }
四.动态加载类
1.什么是动态加载类 什么是静态加载类
Class.forName 不仅表示类的类类型,还代表了动态加载类。编译时加载是静态加载类,
运行时加载是动态加载类。
请大家区分编译 运行。
2.为何要使用动态加载类
我们写了一个程序 并没有写A类和B类以及start方法
public class Main{ public static void main(String args[]){ if("A".equals(args[0])){ A a=new A(); a.start(); } if("B".equals(args[0])){ B b=new B(); b.start(); } } }
编译:
我们会发现,我们并不一定用到A功能或B功能,可是编译却不能通过。而在日常的项目中,如果我们写了100个功能,因为一个功能的原因而导致所有功能不能使用,明显使我们不希望的。在这里,为什么会在编译时报错呢?new 是静态加载类,在编译时刻就需要加载所有可能使用到的功能。所以会报错。而在日常中我们希望用到哪个就加载哪个,不用不加载,就需要动态加载类。
使用动态加载类时,我们不用定义100种功能,只需要通过实现某种标准(实现某个接口)。
代码:
public class Main{ public static void main(String args[]){ try{ Class c=Class.forName(args[0]); All a=(All)c.newInstance(); a.start(); }catch(Exception e){ e.printStackTrace(); } } } class A implements All{ public void start(){ System.out.println("A....START"); } } class B implements All{ public void start(){ System.out.println("B....START"); } } //接口 interface All{ public void start(); }
总结:推荐大家使用动态加载类。原因如上,即节省了代码,又简洁方便,安全。
学习java反射的时候 看到了这 理解的比较浅显 ,肯定有许多要补充的。慢慢学习 慢慢积累 欢迎评论
五.获取类的方法信息 getMethods()方法获取的是所有的public的函数 包括父类继承
getDeclaredMethods()方法获取的是所有该类自己声明的方法
package reflect; import java.lang.reflect.Method; public class ClassDemo { public static void main(String[] args) { //获取类的信息 首先获取类类型 Class c=Book.class; //获取包名+类名 System.out.println(c.getName()); //获取类名 System.out.println(c.getSimpleName()); /* * Method类 方法对象 * 一个成员就是一个Method对象 * getMethods()方法获取的是所有的public的函数 包括父类继承 * getDeclaredMethods()方法获取的是所有该类自己声明的方法 */ Method []ms=c.getDeclaredMethods(); for(Method method:ms){ //得到方法的返回值类型的类类型 Class returnType=method.getReturnType(); System.out.print("返回值类型:"+returnType+"\t"); //得到方法的名称 System.out.print(method.getName()+"("); //获取参数的类类型 Class[] paramTypes=method.getParameterTypes(); for (Class paramType : paramTypes) { System.out.print(paramType.getName()+" "); } System.out.println(")"); } } } class Book extends Rect{ private int price; private String name; public int getPrice() { return price; } public void setPrice(int price) { this.price = price; } public String getName() { return name; } public void setName(String name) { this.name = name; } } class Rect{ private int width; private int height; public void setRect(int width,int height){ this.width=width; this.height=height; } }
运行结果:
当然还有获得类的成员变量 构造方法 ,实现接口,父类,访问权限,包名,等等。
只要我们记得 无论获得什么 首先要获取类的类类型 ,其它通过阅读api文档 轻而易举~
六.获取指定的方法
getDeclaredMethod(name, parameterTypes) name为方法名 parameterTypes为参数类型数组
举个例子
package reflect; import java.lang.reflect.Method; public class MethodDemo1 { public static void main(String[] args) throws Exception { /* * 若想获取print方法 首先获得类的信息 若想获得类的信息 首先获取类类型 */ A a = new A(); Class c = A.class; Method m1 = c.getDeclaredMethod("print", int.class, int.class); // 方法的反射操作 invoke方法 第一个参数为要操作的对象 Object o = m1.invoke(a, 5, 6);// 和a1.print(5,6) 同样效果 Method m2=c.getDeclaredMethod("print",String.class,String.class); Object o2=m2.invoke(a,"Hello","World");//和a1.print(Hello,World) 同样效果 Method m3=c.getDeclaredMethod("print"); Object o3=m3.invoke(a);//和a1.print() 同样效果 } } class A { public void print(){ System.out.println("A"); } public void print(int a, int b) { System.out.println(a + b); } public void print(String a, String b) { System.out.println(a.toLowerCase() + b.toUpperCase()); } }
运行结果:
11
helloWORLD
A