java反射 一些理解
-
JAVA反射机制
什么是反射:
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;
对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。
条件:
JAVA反射(放射)机制:“程序运行时,允许改变程序结构或变量类型,这种语言称为动态语言”。从这个观点看,Perl,Python,Ruby是动态语言,C++,Java,C#不是动态语言。但是JAVA有着一个非常突出的动态相关机制:Reflection,
用在Java身上指的是我们可以于运行时加载、探知、使用编译期间完全未知的classes。换句话说,Java程序可以加载一个运行时才得知名称的class,获悉其完整构造(但不包括methods定义),并生成其对象实体、或对其fields设值、
或唤起其methods。(百度百科)
尽管java不是动态语言 但是java提供了一个非常重要的API用于完成反射的需求。Reflection
学习:
要学习反射,先来介绍下需要学习或者理解的类(直接抄的API的解释词语) 其实能熟练读懂api比看一些教程有用的多
1、java.lang.Class<T>//
Class
类的实例表示正在运行的 Java 应用程序中的类和接口。 2、java.lang.reflect(包)
java.lang.reflect.Constructor<T> //提供关于类的单个构造方法的信息以及对它的访问权限。
java.lang.reflect.Field //
Field
提供有关类或接口的单个字段的信息,以及对它的动态访问权限。反射的字段可能是一个类(静态)字段或实例字段。 java.lang.reflect.Method //
Method
提供关于类或接口上单独某个方法(以及如何访问该方法)的信息。所反映的方法可能是类方法或实例方法(包括抽象方法)。 java.lang.reflect.Modifier //Modifier 类提供了
static
方法和常量,对类和成员访问修饰符进行解码。 例子:
获取包名,类名.......
public static void main(String[] args) { String strObj= new String();//创建对象,这种方式创建,比较容易理解创建了一个String对象 Class classObj = strObj.getClass();//获取了一个运行中的实例模型 有兴趣的可以去读一下源码,就不往外贴了 System.out.println(classObj.getName());//完整类名
System.out.println(classObj.getPackage().getName());//包名
//Result java.lang.String java.lang
}
实例化Class对象的方式:通常理解实例化一个类的Class模型,比如我使用的String这个类,就是实例化了一个String的Class的模型对象
public static void main(String[] args) throws Exception { Class<?> classObj = null; classObj = Class.forName("java.lang.String");//返回与带有给定字符串名的类或接口相关联的 Class 对象。(API) System.out.println(classObj.getName()); classObj=new String().getClass(); System.out.println(classObj.getName()); classObj=String.class; System.out.println(classObj.getName()); //Result java.lang.String java.lang.String java.lang.String }
public static void main(String[] args) throws Exception { Class<?> classObj = null; classObj = Class.forName("java.lang.String");//返回与带有给定字符串名的类或接口相关联的 Class 对象。(API) System.out.println(classObj.getSuperclass().getName());//父类名 Class[] classList=classObj.getInterfaces();//接口列表 for (Class obj: classList) { System.out.println(obj.getName());//实现的接口 } //Result java.lang.Object 默认所有的类都是继承Object类 // java.io.Serializable // java.lang.Comparable // java.lang.CharSequence }
上方这些在Class的API都有详细介绍
通过反射实例化一个类的对象:
两种方式使用类的默认构造方法,指定一个构造方法
public class Test { public static void main(String[] args) throws Exception { //---------------------------------- //第一种 Class<?> classObj = null; classObj = Class.forName("com.jctl.cloud.test.Student");//返回与带有给定字符串名的类或接口相关联的 Class 对象。(API) Student student = (Student) classObj.newInstance(); student.setName("明"); System.out.println(student.toString()); //第二种 Constructor<?> cons[] = classObj.getConstructors();//获取所有的构造方法 for (Constructor constructor: cons) { Class<?> [] params= constructor.getParameterTypes(); for (Class param : params) { System.out.println(param.getName()); } System.out.println("****************************");//打印几次说明有几个构造方法啊 } Student student1 = (Student) cons[1].newInstance("marry",10); System.out.println(student1.toString()); } } class Student{ private String name; private Integer age; public Student() { } public Student(String name, Integer age) { this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } @Override public String toString() { return "Student{" + "name='" + name + '\'' + ", age=" + age + '}'; } }
控制台:
//Result
Student{name='明', age=null}
****************************
java.lang.String
java.lang.Integer
****************************
Student{name='marry', age=10}
获取类的全部属性
public static void main(String[] args) throws Exception { //---------------------------------- //第一种 Class<?> classObj = null; classObj = Class.forName("com.jctl.cloud.test.Student");//返回与带有给定字符串名的类或接口相关联的 Class 对象。(API) Field[] fields= classObj.getDeclaredFields(); for (Field field: fields) { //修饰符 + 类型 + 名字 System.out.println(Modifier.toString(field.getModifiers()) +" "+field.getType().getSimpleName()+" "+field.getName()); } }
//console
修改类的属性无视private
public static void main(String[] args) throws Exception { //---------------------------------- //第一种 Class<?> classObj = null; classObj = Class.forName("com.jctl.cloud.test.Student");//返回与带有给定字符串名的类或接口相关联的 Class 对象。(API) Object object=classObj.newInstance(); Field field = classObj.getDeclaredField("name");// 返回一个 Field 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明字段。 field.setAccessible(true); field.set(object, "xiaomei"); System.out.println(field.get(object));// field.get(Object obj) 反回指定对象上此 Field 表示的字段的值。 }
//console
获取类的全部方法
先给上面的Student类增加一个方法
public void doHomeWork(){ System.out.println(this.name+"开始写作业了!"); }
public void doHomeWork() {
System.out.println("开始写作业了!");
}
public static void main(String[] args) throws Exception { //---------------------------------- //第一种 Class<?> classObj = null; classObj = Class.forName("com.jctl.cloud.test.Student");//返回与带有给定字符串名的类或接口相关联的 Class 对象。(API) Method[] methods = classObj.getDeclaredMethods(); for (Method method : methods) { System.out.println( Modifier.toString(method.getModifiers())+" "//修饰符 +method.getGenericReturnType().toString()+" "+//返回值 method.getName()) ;//方法名 } //public class java.lang.String toString // public class java.lang.String getName //public void setName // public class java.lang.Integer getAge // public void setAge //public void doHomeWork }
直接调用类的方法:
public static void main(String[] args) throws Exception { Class<?> classObj = null; classObj = Class.forName("com.jctl.cloud.test.Student");//返回与带有给定字符串名的类或接口相关联的 Class 对象。(API) Method methods = classObj.getMethod("doHomeWork"); methods.invoke(classObj.newInstance()); //控制台 null开始写作业了! Method methods1 = classObj.getMethod("doHomeWork",String.class); methods1.invoke(classObj.newInstance(),"\"小明\"");
//控制台 小明开始写作业了! }
写了这些反射在java中怎么使用和基本用法,总得做点什么,下一篇反射在代理模式中的应用----------->>>