反射与类操作

操作类(用于范例,演示效果):

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("小秘密");
	}
}

用于理解反射的作用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值