操作类(用于范例,演示效果):
interface IMessage{
public String sign="Message";
public void send();
}
abstract class Message{
protected String tab="IMessage";
public String info="abstract";
}
class QQMessage extends Message implements IMessage{
private String msg=null;
public String name="QQ";
public QQMessage() {
System.out.println("no thing");
}
public QQMessage(String msg) {
this.msg=msg;
System.out.println(msg);
}
public void setMessage(String msg) {
this.msg=msg;
}
public String getMessage() {
return msg;
}
public void send() {
System.out.println("QQ message");
}
public String toString() {
return msg;
}
}
反射获取类结构信息
类结构:父类(父接口),包,属性,方法(构造方法,普通方法)
- 获取包名称:
public Package getPackage();
- 获取父接口:
public Class<?>[] getInterfaces();
- 获取父类:
public Class<? super T> getSuperclass();
public class FactoryTest {
public static void main(String[] args) {
Class<?> cla=QQMessage.class;
Package pack=cla.getPackage();
System.out.println(pack.getName());
}
}
- 获取构造方法:
- 实例化方法替代:
clazz.getDeclaredConstructor().newInstance();
(所有类的构造方法都可以通过Class类完成。)- 获取所有构造方法:
public Constructor<?>[] getDeclaredConstructors() throws SecurityException
- 获取指定构造方法:
public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) throws NoSuchMethodException,SecurityException
- 获取公有所有构造方法:
public Constructor<?>[] getConstructors() throws SecurityException
- 获取公有指定构造方法:
public Constructor<T> getConstructor(Class<?>... parameterTypes) throws NoSuchMethodException,SecurityException
- 获取所有构造方法:
- 实例化方法替代:
Constructor对象:
- 提供的实例化方法操作:
public T newInstance(Object... initargs) throws InstantiationException,IllegalAccessException,IllegalArgumentException,InvocationTargetException
范例:调用指定构造实例化对象
import java.lang.reflect.Constructor;
public class ClaTest {
public static void main(String[] args) throws Exception {
Class<?> instance=QQMessage.class;
// Constructor<?>[] cons=instance.getDeclaredConstructors();
// for(Constructor<?> con:cons) {
// System.out.println(con);
// }
Constructor<?> con=instance.getDeclaredConstructor(String.class);
Object obj=con.newInstance("你好");
System.out.println(obj);
}
}
反射获取类中普通方法
前提:类中要提供有实例化对象
- 获取本类全部方法:
public Method[] getDeclaredMethods() throws SecurityException
- 获取本类指定方法:
public Method getDeclaredMethod(String name,Class<?>... parameterTypes) throws NoSuchMethodException,SecurityException
- 获取公有全部方法:
public Method[] getMethods() throws SecurityException
- 获取公有指定方法:
public Method getMethod(String name,Class<?>... parameterTypes) throws NoSuchMethodException,SecurityException
获取全部方法的使用
public static void methodUsing(Class<?> instance) {
Method meth[]=instance.getMethods();
for(Method temp:meth) {
System.out.println(temp);
}
System.out.println("\n\n\n********************");
Method meth2[]=instance.getDeclaredMethods();
for(Method temp:meth2) {
System.out.println(temp);
}
}
此时,方法信息的获取是通过Method类中的toString方法完成的。可以由用户自己组织输出形式。
Method类中有一个重要的方法:public Object invoke(Object obj,Object... args) throws IllegalAccessException,IllegalArgumentException,InvocationTargetException
反射实现setter,与getter方法的调用
范例:不导入开发包的情况下实现属性的配置。
public static void attributeUsing(Class<?> classname) throws Exception {
//要传入的内容
String value="this is transfer attribute...";
//要想传值,需要先实例化对象
Object obj=classname.getDeclaredConstructor().newInstance();
//获取指定方法
String methodname="setMessage";
Method meth=classname.getDeclaredMethod(methodname, String.class);
meth.invoke(obj, value);
String methodname1="getMessage";
Method meth1=classname.getMethod(methodname1);
System.out.println(meth1.invoke(obj));
}
没有任何明确的对象产生。避免了与某一个类的耦合问题?
反射调用成员
也是通过Class类完成的。
两组操作方法:
- 获取本类全部成员:
public Field[] getDeclaredFields() throws SecurityException
- 获取本类指定成员:
public Field getDeclaredField(String name) throws NoSuchFieldException,SecurityException
- 获取public公有全部成员:
public Field[] getFields() throws SecurityException
- 获取public公有指定成员:
public Field getField(String name) throws NoSuchFieldException,SecurityException
范例:
public static void main(String[] args) throws Exception {
Class<?> instance=QQMessage.class;
fieldUsing(instance);
}
public static void fieldUsing(Class<?> classname) {
Field fies[]=classname.getFields();
for(Field fi:fies) {
System.out.println(fi);
}//会取得其与父类,父接口中public属性
}
Field类中的重要方法:
- 获取成员类型:
public Class<?> getType()
(最常用,获取完整类名称) - 设置属性内容:
public void set(Object obj,Object value)
- 获取属性内容:
public Object get(Object obj)
- 解除封装:
public void setAccessible(boolean flag)
范例:查看类中所有成员,直接调用类中私有成员,获取成员类型
public static void fieldUsing(Class<?> classname) throws Exception {
//1
Field fies[]=classname.getFields();
for(Field fi:fies) {
System.out.println(fi);
}
//会取得所有public属性(包括继承,引入)
System.out.println("----------------");
//2
Object obj=classname.getConstructor().newInstance();
Field fie=classname.getDeclaredField("msg");
fie.setAccessible(true);
fie.set(obj, "tranfer attibute");
System.out.println(fie.get(obj));
fie.setAccessible(false);//写不写都不会报错
//一般不用,不建议打破类的封装
System.out.println("----------------");
//3
Field field=classname.getDeclaredField("msg");
System.out.println(field.getType().getName());
System.out.println(field.getType().getSimpleName());
}
Unsafe工具类
sun.misc.Unsafe
除了JVM提供有反射,Java中还有Unsafe类。
利用反射获取对象,直接使用C++代替JVM执行,可以绕过JVM相关对象管理机制。
即使用了Unsafe,无法使用JVM提供的内存管理机制和垃圾回收处理。
Unsafe类的一些构造方法和常量:
- 构造方法:
private Unsafe() {}
- 私有常量:
private static final Unsafe theUnsafe = new Unsafe();
范例:使用Unsafe类绕过实例化对象的管理。
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import sun.misc.Unsafe;
public class ClaTest {
public static void main(String[] args) throws Exception {
Class<?> instance=QQMessage.class;
unsafeStudy();
}
public static void unsafeStudy() throws Exception {
Field field=Unsafe.class.getDeclaredField("theUnsafe");
field.setAccessible(true);
Unsafe unsafeobj=(Unsafe)field.get(null);//static常量不需要传递实例化对象
//通过Unsafe类绕过JVM的管理机制,在没有获取实例化对象时调用其成员方法
Singleton single=(Singleton)unsafeobj.allocateInstance(Singleton.class);
single.print();
}
}
class Singleton{
private Singleton() {}
public void print() {
System.out.println("小秘密");
}
}
用于理解反射的作用。