反射的作用,参考http://blog.youkuaiyun.com/ritterliu/article/details/7764849
下面介绍几个反射的用法:
1.Class的对象获取
package com.note;
/*
* 在java的世界里,万事万物皆是对象。两个不是:普通变量,和静态成员
*
* 一般类是java.lang.Class的对象:Class构造方法是私有的,所以不能new Class();
*/
public class ClassDemo {
public static void main(String [] args) {
Foo foo1 =new Foo();
//Class实例对象,3种表示方式;
//1.第一种。实际告诉我们任何一个类都有一ig隐含的静态成员变量claas
Class c1= Foo.class;
//2.第二种。已知该类的对象
Class c2 =foo1.getClass();
//3.第三种:属于动态加载类型。编译时加载类就是静态,运行时加载是动态
//new都是静态加载类,全部正确且存在才能编译通过。而动态加载不需要
Class c3= null;
try {
c3= Class.forName("com.note.Foo");
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//官网:c1,c2表示了Foo类的类类型
//结果均为true
System.out.println(c1==c2);
System.out.println(c3==c2);
//我们可以通过类 的类类型创建该类的对象实例-----》通过c1/c2/c3创建Foo的实例
//c1是什么类类型,就创建什么类的实例,需要强制转换,和抛出异常
try {
Foo foo =(Foo)c1.newInstance();
foo.print();
} catch (InstantiationException | IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
//不能用public修饰
class Foo{
void print(){
System.out.println("foo");
}
}
public class ClassDemo1 {
public static void main(String[] args){
try{
//动态加载,编译能通过,运行时才加载类
Class c = Class.forName("args[0]");
//officeAble是一个接口,WORD和excel实现了这个接口,
//所以不管c为word还是excel都能正确创建下面对象
OfficeAble oa = (OfficeAble)c.newInstance();
oa.print();
}catch(Exception e){
}
}
}
3.通过反射获取一个类的成员变量、方法、构造函数:
package com.note;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
//获取类的全部信息
public class ClassUtil {
String s1;
int i1;
public static void main(String[] args) {
Class c0 = int.class;
Class c2 = String.class;
//就是void也是类 ,皆是类
// Class c3 = void.class;
//
// System.out.println(c0.getName());
// System.out.println(c2.getName());
// //不含包名的名称
// System.out.println(c2.getSimpleName());
// System.out.println(c3.getName());
//
//调用下面方法,打印类的成员函数
String s="hello";
ClassUtil.printClassMessage_Methods(new ClassUtil());
ClassUtil.printClassMessage_Fields(new ClassUtil());
ClassUtil.printClassMessage_Constructor(s);
}
/*
* 打印类的信息,包括类的成员函数、成员变量
*
*/
public static void printClassMessage_Methods(Object obj){
//1.首先获取类类型
Class c = obj.getClass();
//2.获取类的名称
System.out.println("类的名称:"+c.getName());
/*
* Method类。方法对象
* 一个成员方法就是iyi个Method当对象
* getMethod()方法获取的是所有的public函数,包括父类继承的
* getDeclaredMethods()获取的是所有该类自己声明的方法,不问访问权限
*/
Method[] ms=c.getMethods();//c.getDeclaredMethods()
for(int i=0;i<ms.length;i++){
//得到方法的返回值类型的类类型
Class returnType = ms[i].getReturnType();
System.out.print(returnType.getName()+" ");
//得到方法的名称
System.out.print(ms[i].getName()+"(");
//获取参数类型----》 得到的参数列表的类型的类类型
Class[] paramTypes = ms[i].getParameterTypes();
for(Class class1:paramTypes){
System.out.print(class1.getName()+",");
}
System.out.println(")");
}
}
public static void printClassMessage_Fields(Object obj){
/*
* 成员变量也是对象.java.lang.reflect.Field
* Field类封装了关于成员变量的操作
* getFileds()方法获取的是所有的public成员变量的信息
* getDeclaredFields()获取的是该类自己声明的成员变量的信息
*/
Class c = obj.getClass();
Field[] fs= c.getDeclaredFields();
for(Field field:fs){
//得到成员变量的类类型
Class fieldType = field.getType();
System.out.print(fieldType.getName()+" ");
//得到成员变量的名字
System.out.println(field.getName());
}
}
//获取对像的构造函数信息
public static void printClassMessage_Constructor(Object obj){
Class c= obj.getClass();
/*
* 构造函数也是对象
* java.lang.Construtor中封装了构造函数的信息
* getConstruts()获取所有的public的构造函数
* getDeclaredConstruts的得到自己声明的构造函数
*
*/
Constructor[] cs = c.getDeclaredConstructors();
for(Constructor constructor:cs){
System.out.print(constructor.getName()+"(");
//得到参数类型
Class paramTypes[] = constructor.getParameterTypes();
for(Class class1:paramTypes){
System.out.print(class1.getName()+",");
}
System.out.println(")");
}
}
}
4.方法的反射:
package com.note;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/*
* 方法的反射:
* * 1.获取方法
* 2.通过方法反射
*/
public class ClassInvoke {
public static void main(String[] args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
//要获取print(int,int)方法
A a1 = new A();
//获取方法 名称和参数列表来决定c.getMethod(name,Class... parameters)
Class c = a1.getClass();
//此处会抛出异常,方法不存在或者
try {
//Method m = c.getMethod("print",int.class,int.class);也可以
Method m = c.getMethod("print",new Class[]{int.class,int.class});
//方法的反射操作
//a1.print(10,20);方法的反射操作是用m对象来进行方法调用和a1.print调用的效果
//方法有返回值返回返回值,没有返回值返回void
Object o=m.invoke(a1, new Object[]{10,20});//(a1, 10,20);
System.out.println("============");
A a2= new A();
Class c1 =a2.getClass();
Method m1 = c1.getMethod("print",String.class,String.class);
m1.invoke(a2,"ss","BBB");
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
class A{
public void print(int a ,int b){
System.out.println(a+b);
}
public void print(String a ,String b){
System.out.println(a.toUpperCase()+","+b.toLowerCase());
}
}
5.反射绕过编译。都是在编译之后
package com.note;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
//泛型问题。ArrayList<String>为泛型
public class ClassMethod {
public static void main(String[] args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException{
ArrayList list1 = new ArrayList ();
ArrayList<String> list2 = new ArrayList<String>();
Class c1 = list1.getClass();
Class c2= list2.getClass();
//结果为TRUE
System.out.println(c1==c2);
/*
* 集合的泛型是防止错误输入的,只在编译阶段有效,即不能在list2中插入部位String类型的
*反射是的操作都是编译之后的操作
*c1=c2,表明集合的泛型都是在编译阶段有效
*我们可以通过方法的反射绕过编译
*/
try {
Method m = c2.getMethod("add",Object.class);
m.invoke(list1,20);
System.out.println(list1);
} catch (NoSuchMethodException | SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}