java-反射

目录

一,基本概念

 二,通过反射创建对象

三,通过反射访问成员变量并赋值

 四,通过反射访问方法并赋值


一,基本概念

Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为Java语言的反射机制。

根据虚拟机的工作原理,一般情况下,类需要经过:加载->验证->准备->解析->初始化->使用->卸载这个过程,如果需要反射的类没有在内存中,那么首先会经过加载这个过程,并在在内存中生成一个class对象,有了这个class对象的引用,就可以发挥开发者的想象力,做自己想做的事情了。

  1. 使用“类对象”来执行反射操作,这里的类对象并不是new出来的对象,而是方法区被加载的类;
  2. 通过反射可以获得一个类的定义信息;
  3. 通过反射创建对象;
  4. 通过反射调用成员变量和方法;
  5. 获得类对象的三种方式:
  • 通过类名.class;
  • Class.forName("完整路径的类名")
  • a.getClass()

下面通过案例来演示:

public class ToOtherFather {
	private String s1="1";//私有成员变量
	public char c=1;//公有成员变量

	public ToOtherFather() {}//私有无参构造函数
	public ToOtherFather(String s2) {}//公有有参构造函数
	
	public void method1(float x1,float x2) {}//公有方法
	private void method5() {}//私有方法
	public void method4() {}//公有方法
}
public class ToOther extends ToOtherFather{
	
	private int x=1;//私有成员变量
	public int y=1;//公有成员变量
	
	private float k=2f;//私有成员变量
	public double z=1l;//公有成员变量


	public ToOther() {}//公有无参构造函数
	public ToOther(double y,String s) {}//公有无参构造函数
	private ToOther(int x) {}//私有有参构造函数
	
	@Override
	public void method1(float x1,float x2) {
	}
	
	public void method2(String s) {
		
	}
	
	private void method3(int x,double y) {
		
	}

}
public class Test {

	public static void main(String[] args) {
		
		getName();//获取包名类名
		System.out.println("----------------------------------------------------------------");
		getBianliang();//获取成员变量
		System.out.println("----------------------------------------------------------------");
		getGouzao();//获取所有构造方法
		System.out.println("----------------------------------------------------------------");
		getFangfa();//获取所有方法
		System.out.println("----------------------------------------------------------------");
		
	}

	private static void getName() {
		try {
			Class<?>sClass=Class.forName("反射.ToOther");
			System.out.println(sClass.getName());
			System.out.println(sClass.getPackageName());
			System.out.println(sClass.getPackage().getName());
			System.out.println(sClass.getSimpleName());
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
	}
	
	
	private static void getBianliang() {
		try {
			Class<?>sClass=Class.forName("反射.ToOther");
			Field[]a=sClass.getDeclaredFields();//获取所有成员变量,包括私有,除了继承的变量
			Field[]b=sClass.getFields();//获取所有成员变量,包括继承的变量,除了私有
			
			System.out.println("------获取所有成员变量,除了继承的父类变量,包括私有------");
			for (Field field : a) {
				System.out.println("成员类型"+field.getGenericType()
						+"  成员名称"+field.getName()
						+"  变量所在类:"+field.getDeclaringClass().getSimpleName());
			}
			
			System.out.println();
			System.out.println("------获取所有成员变量,包括继承父类的变量,除了私有------");
			for (Field field : b) {
				System.out.println("成员类型"+field.getType().getSimpleName()
						+"  成员名称"+field.getName()
						+"  变量所在类:"+field.getDeclaringClass().getSimpleName());
			}
			
			System.out.println();
			try {
				System.out.println("------getField()获取单个成员变量,除了私有成员------");
				Field c=sClass.getField("y");
				System.out.println(c.getName());
				
				System.out.println("------getDeclaredField()获取单个成员变量,除了私有成员------");

				Field d=sClass.getDeclaredField("x");
				System.out.println(d.getName());
				
			} catch (Exception e) {
				e.printStackTrace();
			} 
			
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
	}
	
	private static void getGouzao() {
		try {
			Class<?>sClass=Class.forName("反射.ToOther");
			
			System.out.println("------获取所有构造函数,除了私有构造函数------");
			Constructor<?>[]a=sClass.getConstructors();
			for (Constructor<?> c : a) {
				Class<?>[]p=c.getParameterTypes();//构造方法参数列表
				System.out.println(sClass.getSimpleName()+"  "+
						Arrays.toString(p)
						);
				
			}
			
			System.out.println();
			System.out.println("------获取所有构造函数,包括私有构造函数------");
			Constructor<?>[]b=sClass.getDeclaredConstructors();
			for (Constructor<?> c : b) {
				Class<?>[]p=c.getParameterTypes();//构造方法参数列表
				System.out.println(sClass.getSimpleName()+"  "+
						Arrays.toString(p)
						);
				
			}
			
			System.out.println();
			System.out.println("------通过参数列表,获取单个构造函数,不包括私有构造函数------");
			Constructor s2=sClass.getConstructor(double.class,String.class);
			Class<?>[]p=s2.getParameterTypes();//构造方法参数列表
			System.out.println(sClass.getSimpleName()+"  "+
					Arrays.toString(p)
					);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private static void getFangfa() {
		try {
			Class<?>sClass=Class.forName("反射.ToOther");
			
			System.out.println("------获取所有方法,包括父类,除了私有方法------");
			Method[]a=sClass.getMethods();
			
			for (Method method : a) {
				Class<?>[]p=method.getParameterTypes();
				System.out.println(
					method.getName()+"  "+
						Arrays.toString(p));
			}
			
			System.out.println();
			System.out.println("------获取所有方法,不包括父类,包括私有方法------");

			Method[] b=sClass.getDeclaredMethods();
			
			for (Method method : b) {
				Class<?>[]p=method.getParameterTypes();
				System.out.println(
					method.getName()+"  "+
						Arrays.toString(p));
			}
			
			System.out.println();
			System.out.println("------获取单个方法------");

			Method c=sClass.getMethod("method1", float.class,float.class);
			Class<?>[]p=c.getParameterTypes();

			System.out.println(
					c.getName()+"  "+Arrays.toString(p));
			
		} catch (Exception e) {
			
		}
	}

}

打印输出结果:

反射.ToOther
反射
反射
ToOther
----------------------------------------------------------------
------获取所有成员变量,除了继承的父类变量,包括私有------
成员类型int  成员名称x  变量所在类:ToOther
成员类型int  成员名称y  变量所在类:ToOther
成员类型float  成员名称k  变量所在类:ToOther
成员类型double  成员名称z  变量所在类:ToOther

------获取所有成员变量,包括继承父类的变量,除了私有------
成员类型int  成员名称y  变量所在类:ToOther
成员类型double  成员名称z  变量所在类:ToOther
成员类型char  成员名称c  变量所在类:ToOtherFather

------getField()获取单个成员变量,除了私有成员------
y
------getDeclaredField()获取单个成员变量,除了私有成员------
x
----------------------------------------------------------------
------获取所有构造函数,除了私有构造函数------
ToOther  [double, class java.lang.String]
ToOther  []

------获取所有构造函数,包括私有构造函数------
ToOther  [int]
ToOther  [double, class java.lang.String]
ToOther  []

------通过参数列表,获取单个构造函数,不包括私有构造函数------
ToOther  [double, class java.lang.String]
----------------------------------------------------------------
------获取所有方法,包括父类,除了私有方法------
method1  [float, float]
method2  [class java.lang.String]
method4  []
wait  [long]
wait  [long, int]
wait  []
equals  [class java.lang.Object]
toString  []
hashCode  []
getClass  []
notify  []
notifyAll  []

------获取所有方法,不包括父类,包括私有方法------
method1  [float, float]
method2  [class java.lang.String]
method3  [int, double]

------获取单个方法------
method1  [float, float]
----------------------------------------------------------------

 

总结:

getDeclaredFields()

获取所有成员变量,包括私有,除了继承的变量

  

getFields()

获取所有成员变量,包括继承的变量,除了私有

  

getDeclaredField("x")

获取单个成员变量,包括私有成员

  

getField("y")

获取单个成员变量,除了私有成员

  

getConstructors()

获取所有构造函数,除了私有构造函数

  

getDeclaredConstructors()

获取所有构造函数,包括私有构造函数

  

getConstructor(double.class,String.class)

通过参数列表,获取单个构造函数,不包括私有构造函数

  

getDeclaredConstructor(double.class,String.class)

通过参数列表,获取单个构造函数,包括私有构造函数

  

getMethods()

获取所有方法,包括父类,除了私有方法

  

getDeclaredMethods()

获取所有方法,不包括父类,包括私有方法

  

getMethod("method1", float.class,float.class)

获取单个方法

  

getDeclaredMethod("method1", float.class,float.class)

获取单个方法

  

 二,通过反射创建对象

  • 通过类对象的反射操作来新建对象,但是在java9之后,该方法不建议使用了;
  • 通过构造方法的反射操作,来新建对象;
public class Test2 {

	public static void main(String[] args) {

		f1();//通过类对象的反射操作,来新建对象
		f2();//通过构造方法的反射操作,来新建对象
	}

	private static void f1() {
		try {
			Class<?>c=Class.forName("反射.ToOther");
			Object o1=c.newInstance();//此方法在java9以后就不建议使用
			System.out.println(o1.toString());
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	private static void f2() {
		try {
			Object o2=null;
			Class<?>c=Class.forName("反射.ToOther");
			o2=c.getConstructor(double.class,String.class).newInstance(11.11,"11.11");
			System.out.println(o2.toString());
			
			//如果是私有构造函数,要进行setAccessible,除了允许访问私有,还有允许设置数值创建
			Object o3=null;
			Class<?>c2=Class.forName("反射.ToOther");
			Constructor<?>t2=c2.getDeclaredConstructor(int.class);
			t2.setAccessible(true);
			o3=t2.newInstance(11);
			System.out.println(o3.toString());
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}
}

打印:

三,通过反射访问成员变量并赋值

public class Test3 {

	public static void main(String[] args) {
		ToOther toOther1=new ToOther();
		ToOther toOther2=new ToOther();
		try {
			Class<ToOther>c=ToOther.class;
			
			//给指定对象的变量赋值
			System.out.println(toOther1);
			Field field=c.getDeclaredField("x");
			field.setAccessible(true);
			field.set(toOther1, 100);
			System.out.println(toOther1);
			
			//如果是静态变量,不用区分是哪个对象的,传null,属于全局
			Field field2=c.getDeclaredField("sum");
			field2.setAccessible(true);
			field2.set(null, 100);
			System.out.println(toOther1);

			//也可以强转
			int sum=(int) field2.get(toOther1);
			System.out.println(sum);
			
			
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

打印:

 四,通过反射访问方法并赋值

public class Test4 {

	public static void main(String[] args) {
		
		//获取方法,并赋值
		ToOther toOther=new ToOther();
		try {
			Class<?>c=Class.forName("反射.ToOther");
			
			Method t1=c.getMethod("setX",int.class);
			Method t2=c.getMethod("getX");
			
			t1.invoke(toOther, 1000);//通过方法给x赋值
			int obj=(int) t2.invoke(toOther); //默认是Object,这里进行了强转
			System.out.println(obj);
	/
			
			Method t3=c.getDeclaredMethod("setK", float.class);
			Method t4=c.getDeclaredMethod("getK");
			t3.setAccessible(true);
			t4.setAccessible(true);
			t3.invoke(toOther, 1000.33f);
			Object obj2=t4.invoke(toOther);
			System.out.println(obj2);
			
			
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}
}

打印结果

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小小苏的小小苏

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值