JAVA中的反射

JAVA中的反射

1.简介:

1.java提供的一套API。
2.提供了检查一个对象的内部结构的手段。
3.反射API可以:
3.1动态加载类.
3.2动态创建对象.
3.3动态访问属性.
3.4动态调用方法。

2.通过反射获取对象的相关属性的方法

1.通过反射可以检查对应的类型的内部结构

动态获取obj类型Object类提供了一个方法getClass()返回一个Class类。

		Class cls=obj.getClass();
		System.out.println("cls的类是"+cls);
2.检查对象类型中声明了那些属性

Class类提供了getDeclaredfields();返回一个Field[]数组。
Declared:声明的,定义的意思。
Fields:字段,属性的意思。

		Field[] field=cls.getDeclaredFields();
		//System.out.println(field.length);
		for(Field f:field){
			System.out.println("cls类中的属性"+f);
		}
3.通过放射获取对象中指定的属性

Class类提供了getDeclaredField(string name)
name:指对象中的属性

		try {
			Field fie=cls.getDeclaredField("hash");
			System.out.println("包含hash的属性是"+fie);
		}catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
4.通过反射获取对象中的所有的方法

Class类提供了getDeclaredMethods()返回Methods[]数组

		Method[] methods=cls.getDeclaredMethods();
		//System.out.println(methods.length);
		for(Method m:methods){
			System.out.println("cls对象中的方法:"+m);
		}
5.通过反射获取对象中指定的方法

Class类提供了getDeclaredMethod(String name,ParemterType type)
name:指方法的名字;
type:指该方法中的参数的类型,如果是多个参数则用“,”隔开;

	try {
        Method       				 method=cls.getDeclaredMethod("valueOf",char[].class,int.class,int.class);
			System.out.println("找到了"+method);
		}catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
6.通过反射获取所有的构造方法

Class类提供了getDeclaredConstructors()返回Constructor[]数组

		Constructor[] cons=cls.getDeclaredConstructors();
		System.out.println(cons.length);
		for(Constructor c:cons){
			System.out.println(c);
		}
7.通过反射获取指定的构造方法

Class类提供了getDeclaredConstructor(ParemterType type,…)返回Constructor

		try {
			Constructor con=cls.getDeclaredConstructor(byte[].class,int.class,int.class);
			System.out.println(con);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

2.动态加载类

1.通过反射动态加载类,返回一个Class实例

通过反射动态加载类,Class类提供了一个静态方法ForName(string className) 返回一个class实例

	public class ClassForNmaeReflect {
	public static void main(String[] args) {
		Scanner scanner=new Scanner(System.in);
		System.out.println("请输入类名:");//包名+类名
		String className=scanner.next();
		 
        
		try {
			Class cls=Class.forName(className);
			//在Class类中提供了newInstance()来创建对象的实例化
			Object obj=cls.newInstance();
			System.out.println("输出:"+bj);
			
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

自定义类Demo:

public class Demo {
	private String name="bat";
	public int age=1;
	public void run(){
		System.out.println("bat牛啊!");
	}
	
	private String run2(String name,int age){
		System.out.println(name+",今年:"+age+"岁");
		return "成功!";
	}
	
	static{
		System.out.println("静态块");
	}

	
	public String toString() {
		return "Demo [name=" + name + ", age=" + age + "]";
	}
	
	
}
执行结果:

请输入类名:
day16.Demo

输出:静态块Demo

[name=bat, age=1]

2.通过反射动态加载类只加载一次
public class ClassForNmaeReflect02 {
	public static void main(String[] args) {
		Scanner scanner=new Scanner(System.in);
		System.out.println("请输入类名:");//包名+类名
		String className=scanner.next();
		
		//动态加载类
		try {
			Class cls=Class.forName(className);
			Class cls1=Class.forName(className);
			Class cls2=Class.forName(className);
			System.out.println(cls==cls1);
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		}
	}
}
执行结果:

请输入类名:
day16.Demo
静态块
true

3.通过反射获取对象中的属性值及其私有属性

1.Field提供了一个方法setAccessible(true),该方法可以打开原有的私有属性的访问权限,还可以打开任何不可见的属性,方法的访问权限在获取属性或者方法值之前打开该访问权限 。

2.在object对象上获取属性的值,Field提供了一个方法get(object obj),从而获取到对象中的指定属性。

3.属性名是用户运行期间输入的,输入的那个属性名这段程序就会输出哪个属性的值,也就是意味,程序与属性之间是松耦合关系。

public class ClassForNmaeReflect03 {
	public static void main(String[] args) {
		Scanner scanner=new Scanner(System.in);
		System.out.println("请输入类名:");//包名+类名
		String className=scanner.next();
		System.out.println("请输入属性名:");//方法名或属性
		String methodName=scanner.next();
		
		//动态加载类
		try {
			Class cls=Class.forName(className);
			//通过反射获取对象中指定的属性
			Field field=cls.getDeclaredField(methodName);
			//通过反射创建对象
			Object obj=cls.newInstance();
			/*
			 *field提供了一个方法setAccessible(true),该方法可以打开原有的私有属性
			 *的访问权限,还可以打开任何不可见的属性,方法的访问权限
			 *在获取属性或者方法值之前打开该访问权限 
			 */
			field.setAccessible(true);
			
			//在object对象上获取属性的值,field提供了一个方法get(object obj),
			//从而获取到对象中的指定属性
			Object ob=field.get(obj);//动态获取属性值
			/*
			 * 属性名是用户运行期间输入的,输入的那个属性名这段程序就会输出哪个属性的值,
			 * 也就是意味,程序与属性之间是松耦合关系。
			 */
			System.out.println(field+",的值是"+ob);
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		}
	}
}
执行结果:

请输入类名:
day16.Demo
请输入属性名:
age
静态块
public int day16.Demo.age,的值是1

4.通过反射动态获取对象中的方法返回值

1.Method提供了invoke(OBject obj,Paremter(参数),…)获取方法体
public class ClassForNmaeReflect04 {
	public static void main(String[] args) {
		Scanner scanner=new Scanner(System.in);
		System.out.println("请输入类名:");//包名+类名
		String className=scanner.next();
		System.out.println("请输入方法名:");//方法名或属性
		String methodName=scanner.next();
		
		//动态加载类
		try {
			Class cls=Class.forName(className);
			//通过反射获取指定的方法
			Method method=cls.getDeclaredMethod(methodName, String.class,int.class);
			//通过反射创建对象实例化
			Object obj=cls.newInstance();
			//打开访问权限
			method.setAccessible(true);
			//Method提供了invoke(OBject obj,Paremter(参数),..)获取方法体
			Object ob=method.invoke(obj,"超",20);
			//获取方法的返回值,如果没有返回值,则返回null
			System.out.println(ob);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}
执行结果:

请输入类名:
day16.Demo
请输入方法名:
run2
静态块
超,今年:20岁
成功!

2.getDeclaredMethod和getMethod区别:

getDeclaredMethod:获取当前类Class中的方法。

getMethod:获取当前类中的所有方法。

5.通过反射动态调用该对象的方法

1.设置抽象类HttpServlet
public abstract class HttpServlet {
	public abstract void service(String name,int age);
}
2.LoginServlet继承抽象类HttpServlet并重写service方法
public class LoginServlet extends HttpServlet{
	public void service(String name,int age){
		System.out.println("这是LoginServlet()");
	}
}
3.同过反射调用该对象的方法
public class ClassForNmaeReflect06 {
	public static void main(String[] args) {
		Scanner scanner=new Scanner(System.in);
		System.out.println("请输入类名:");//包名+类名
		String className=scanner.next();
		try {
			//动态加载类
			Class cls=Class.forName(className);
			//通过反射创建实例化
			HttpServlet obj=(HttpServlet)cls.newInstance();
			obj.service("liu",33);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}
执行结果:

请输入类名:
day16.LoginServlet
这是LoginServlet()

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值