反射,一种计算机处理方式。是程序可以访问、检测和修改它本身状态或行为的一种能力(百度百科)。
在很多时候我们示例话对象的时候是通过一个关键字new来实现的,并对类的成员进行操作。而反射是通过一个特殊的类的类型来实现我们要对一个类的所有操作.
实例化一个Class类对象方法:
• public static Class<?> forName(String className)
【该方法的前提是知道一个类的全名(包名.类名)】
•public final Class<?> getClass()
【该方法可以获取类的Class类型的对象,但是前提是要先实例化类的本类对象,之后使用本类对象的getClass()方法获取】
•直接使用“类名称.class”
示例:
/-/工具类,上下文会用到:
package com.zhaoqiang.reflex;
public class Person {
private String name;
private int age;
public Person(){}
public Person(String name){
this.name = name;
}
public Person(String name, int age){
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public void say(){
System.out.println("我是中国人,我说中文");
}
public void say(String str){
System.out.println("狗娃是楚国人,它会背楚辞");
}
private void eat(){
System.out.println("北方吃面条,南方吃米饭,西红柿放盐");
}
}
package com.zhaoqiang.reflex;
import java.util.Date;
public class Demo1 {
public static void main(String[] args) {
//第一种: 实例化一个本类对象
Date date = new Date();
Class<?> cls1 = date.getClass();
// Person类是自己定义的类
// 第二种:获取类的全名(虚拟路径:包名.类名)
// 此方法会抛出一个异常ClassNotFoundException
try {
Class<?> cls2 = Class.forName("/com.zhaoqiang.reflex.Person");
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// 第三种:通过类名实例化一个Class对象
Class<?> cls3 = Person.class;
}
}
创建了Class类对象我们就可以通过Class类对象来创建一个本类对象。
•public T newInstance() throws InstantiationException,
示例:
package com.zhaoqiang.reflex;
import java.util.Date;
public class Demo1 {
public static void main(String[] args) throws Exception {
//第一种: 实例化一个本类对象
// Date date = new Date();
// Class<?> cls1 = date.getClass();
// 第二种:获取类的全名(虚拟路径:包名.类名)
// 此方法会抛出一个异常ClassNotFoundException
try {
Class<?> cls2 = Class.forName("com.zhaoqiang.reflex.Person");
// 通过Class对象实例化Person对象
Person per = (Person)cls2.newInstance();
System.out.println(per.toString());
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// 第三种:通过类名实例化一个Class对象
// Class<?> cls3 = Person.class;
// 通过Class对象创建一个本类对象
}
}
下面是一个简单工厂类使用反射来实现。
示例:
package com.zhaoqiang.reflex;
interface Comput{
public abstract void say();
}
class HS implements Comput{
@Override
public void say() {
System.out.println("正在使用hs电脑");
}
}
class DE implements Comput{
@Override
public void say() {
System.out.println("正在使用de电脑");
}
}
class Factory{
public static Comput getInstance(String className){
try {
Class<?> cls = Class.forName(className);
return (Comput) cls.newInstance();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
}
public class Demo2 {
public static void main(String[] args) {
Comput cp = Factory.getInstance("com.zhaoqiang.reflex.HS");
cp.say();
}
}
通过Class对象实例化了类对象,一个类对象可能有很多个构造方法,如果类中没有默认构造函数,那么使用上的方法实例化对象就会报错。下面是通过Class对象获取类的构造函数方法:
•public Constructor<T> getConstructor(Class<?>... parameterTypes)
【获取指定的构造方法】
•public Constructor<?> [] getConstructors() throws SecurityException
【获取所有的构造方法】
示例:
package com.zhaoqiang.reflex;
import java.lang.reflect.Constructor;
public class Demo3 {
public static void main(String[] args) throws Exception {
Class<?> cls = Person.class;
// 获取一个无参的构造方法
Constructor<?> cons = cls.getConstructor();
// 获取指定的构造函数
Constructor<?> cons2 = cls.getConstructor(String.class);
Person per1 = (Person)cons2.newInstance("张三");
// 获取两个参数的指定构造函数
Constructor<?> cons3 = cls.getConstructor(String.class,int.class);
Person per2 = (Person)cons3.newInstance("李四",18);
// 获取所有的构造方法
Constructor<?> consarray[] = cls.getConstructors();
// 特别注意:所有获取的构造方法排序是从构造方法中参多的排在第一个
}
}
通过反射调用类中普通方法:
•public Method getMethod(String name,Class<?>... parameterTypes)
【获取指定参数的普通方法,第一个参数是方法名称,参数列表的Class类类型】
•public Method[] getMethods() throws SecurityException
【获取所有的普通方法】
这里出现了一个新的类:Mehtod类,该类专门对象普通方法进行操作,要执行普通方法则需要该类中的一个方法:
•public Object invoke(Object obj, Object... args)
【执行该方法,第一个参数是对象的名称,第二个参数是方法中传递的参数】
示例:
package com.zhaoqiang.reflex;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
public class Demo4 {
public static void main(String[] args) throws Exception {
Class<?> cls = Person.class;
Constructor<?> con = cls.getConstructor(String.class,int.class);
Person per = (Person) con.newInstance("狗娃",16);
// 无参
Method mt = cls.getMethod("say");
mt.invoke(per);
// 有参
Method mt2 = cls.getMethod("say", String.class);
mt2.invoke(per, "狗娃");
// 获取所有的方法
Method[] mt3 = cls.getMethods();
}
}
通过反射调用类中成员变量:
•public Field getDeclaredField(String name)
【获取指定的属性】
•public Field[] getDeclaredFields() throws SecurityException
【获取所有的属性】
在上面的方法中又出现了一个新的类 Field,该类是专门对属性进行操作的,在该了中又提供了两个方法
|- public String getName()【获取属性的名称】
|- public Object get(Object obj)【获取属性对应的值】
|- public void set(Object obj, Object value)【为属性设置值】
示例:
package com.zhaoqiang.reflex;
import java.lang.reflect.Field;
public class Demo5 {
public static void main(String[] args) throws Exception {
Class<?> cls = Person.class;
Person per = (Person) cls.newInstance();
// 获取指定的属性
Field f = cls.getDeclaredField("name");
// 获取所有的属性
Field[] farray = cls.getDeclaredFields();
// 获取属性名称
farray[0].getName();
// 取消private封装
f.setAccessible(true);
// 设置值
f.set(per, "狗娃");
// 获取属性对于的值
farray[0].get(per);
System.out.println(per.getName());
}
}
java反射的一些简单应用:
示例一:
package com.zhaoqiang.reflex;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
/*
* 要求将Person 对象中的属性以及属性值转换成一个指定字符串格式:
* "person":"{"name":"smith","age":"123"}"
* */
public class Test1 {
public static void main(String[] args) throws Exception {
// 获取Class对象
Class<?> cls = Person.class;
// 获取两个参数的构造函数
Constructor<?> con = cls.getConstructor(String.class,int.class);
// 实例化一个Person对象
Person per = (Person) con.newInstance("狗娃",100);
// 获取Person类中所有属性
Field[] f = cls.getDeclaredFields();
// 声明一个StringBuffer对象
StringBuffer sb = new StringBuffer();
sb.append("\"Person\":\"{\"");
for(int i=0; i<f.length; i++){
// 解除封装
f[i].setAccessible(true);
sb.append("\""+f[i].getName()+"\":");
sb.append("\""+f[i].get(per)+"\"");
}
sb.delete(sb.length()-1, sb.length());
sb.append("};");
System.out.println(sb);
}
}
package com.zhaoqiang.reflex;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
/*
* 要求将Person 对象中的属性以及属性值转换成一个指定字符串格式:
* "person":"{"name":"smith","age":"123"}"
* */
public class Test1 {
public static void main(String[] args) throws Exception {
// 获取Class对象
Class<?> cls = Person.class;
// 获取两个参数的构造函数
Constructor<?> con = cls.getConstructor(String.class,int.class);
// 实例化一个Person对象
Person per = (Person) con.newInstance("狗娃",100);
// 获取Person类中所有属性
Field[] f = cls.getDeclaredFields();
// 声明一个StringBuffer对象
StringBuffer sb = new StringBuffer();
sb.append("\"Person\":\"{\"");
for(int i=0; i<f.length; i++){
// 解除封装
// f[i].setAccessible(true);
// 不解除封装,通过方法名获取数据
Method mt = cls.getMethod(initCap(f[i].getName())); // 去的属性对应的get方法
sb.append("\""+f[i].getName()+"\":");
// sb.append("\""+f[i].get(per)+"\"");
sb.append("\""+mt.invoke(per)+"\"");
}
sb.delete(sb.length()-1, sb.length());
sb.append("};");
System.out.println(sb);
}
public static String initCap(String name){
return "get"+name.substring(0,1).toUpperCase()+name.substring(1);
}
}