JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。
通俗易懂的讲可以说我们可以通过反射获得任意一个类或者任意一个对象的所有属性和方法
class类:普通数据类型 静态属性或者方法不是对象属于类
万事万物皆对象
类是Java.lang.Class类的实例对象
任何类都是Class的实例对象
成员变量也是对象,java.lang.reflect.Field Field类封装了关于成员变量的操作
getName()获得类的全称
getMethods()获得方法
getReturnType()获得返回类型
getParameterTypes()获得参数类类型
实际应用案例如下:
案例一:
package fanshe;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
/**
* Created by codessl on 2017/9/5 0005.
*/
//成员变量也是对象,java.lang.reflect.Field Field类封装了关于成员变量的操作
//getFields getDeclaredFields getType
//getName()获得类的全称+getMethods()获得方法+getReturnType()获得返回类型+getParameterTypes()获得参数类类型
public class ClassDemo2 {
public static void main(String[] args) {
Class c1=String.class;
Class c2=void.class;
System.out.println(c1.getName());//全名
System.out.println(c2.getSimpleName());//获取包名之外的类的名称
//getMethods()获得所有的public的函数,包括父类继承而来的对象
//getDeclaredMethods()获取的是所有该类自己声明的方法,不问访问权限
Method[]ms=c1.getMethods();//c.getDeclaredMethods()
for(int i=0;i<ms.length;i++){
Class returnType=ms[i].getReturnType();
System.out.println(returnType.getName());
//获得方法名
System.out.println(ms[i].getName()+"(");
//获取参数类型得到参数列表的类型的类类型
Class[]paramTypes=ms[i].getParameterTypes();
for(Class class1:paramTypes){
System.out.println(class1.getName()+",");
}
System.out.println(")");
}
Field[]fs=c2.getFields();
for(int i=0;i<fs.length;i++){
Class fs1=fs[i].getType();
String name=fs1.getName();//成员变量的类类型
//获取成员变量的名称
String fieldName=fs[i].getName();
System.out.println(name+" "+fieldName);
}
}
}
案例二:获取自定义类的相关信息:
package fanshe;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Iterator;
/**
* Created by codessl on 2017/9/5 0005.
*/
public class ReflectMethod {
public static void main(String args[]) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
test a = new test();
Class c = a.getClass();
Method mt = c.getMethod("printInfo", int.class, int.class);
//printInfo调用a对象的该方法
//具有返回值
Object o= mt.invoke(a, 10,20);
//都是绕过编译在运行时进行
//示例:通过方法的反射绕过泛型
ArrayList<String>list=new ArrayList<String>();
int la=123;
//list.add(la); 编译时会差生错误
Class listClass=list.getClass();//获得类类型
Method limt=listClass.getMethod("add",Object.class);//获得方法
Object oo=limt.invoke(list,la);//开始进行反射
Iterator li=list.iterator();
while(li.hasNext()){
System.out.println(li.next());
}
}
}
class test {
public void printInfo(int a, int b) {
System.out.println(a + "," + b);
}
}
案例三:
(1)Fool类的创建
package fanshe;
/**
* Created by codessl on 2017/9/5 0005.
*/
public class Fool {
}
(2)调用
package fanshe;
/**
* Created by codessl on 2017/9/5 0005.
*/
public class Reflect {
public static void main(String[] args) {
Fool fool=new Fool();
//Foool也是个实例对象,Class类的实例对象,
//任何一个类都是Class类的实例对象,这个对象有三种表示方式
//任何一个类都有一个隐含的静态变量Class,适用于知道类时的情况
Class c1=Fool.class;
//第二种表达方式,已知该类的对象通过getClass方法获取 知道类对象
Class c2=fool.getClass();
//类也是对象被称为class的实例对象,这个对象被称为该类的类类型
//c1 c2代表Fool类的类类型 其他的为其实例对象
System.out.println(c1==c2);
Class c3=null;
try {
c3=Class.forName("fanshe.Fool");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
System.out.println(c2==c3);
//Class.forName("类的全称")动态加载类
//编译时静态加载类,运行时动态加载类
//由类类型得实例对象+无参数构造方法
try {
Fool newfool=(Fool)c1.newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}