JavaSE018_详解反射14例

一、反射的概念

反射主要是指程序可以访问,检测和修改它本身状态或行为的一种能力,并能根据自身行为的状态和结果,调整或修改应用所描述行为的状态和相关的语义。

反射是java中一种强大的工具,能够使我们很方便的创建灵活的代码,这些代码可以在运行时装配,无需在组件之间进行源代码链接。但是反射使用不当会成本很高!

二、反射的作用

1、反编译:.class-->.java;

2、通过反射机制访问java对象的属性,方法,构造方法等;

三、反射的四个类

java.lang.Class;                

java.lang.reflect.Constructor; java.lang.reflect.Field;        

java.lang.reflect.Method;

java.lang.reflect.Modifier;

具体使用方法要查阅API

四、实例代码

【实例1】通过一个对象获得完整的包名和类名(所有类的对象其实都是Class的实例

package com.cctvjiatao.Reflect;
public class Demo {
	//其他代码
}
package com.cctvjiatao.Reflect;
/**
 * 通过一个对象获得完整的包名和类名
 **/
public class Hello {
	public static void main(String[] args) {
		Demo demo = new Demo();
		System.out.println(demo.getClass().getName());
	}
}
【运行结果】:com.cctvjiatao.Reflect.Demo

【实例2】实例化Class的对象,即通过反射机制获取类(共有三种方法)

package com.cctvjiatao.Reflect;
public class Demo {
	//其他代码
}
package com.cctvjiatao.Reflect;
/**
 * 实例化Class类对象的三种方式
 **/
public class Hello {
	public static void main(String[] args) {
		Class<?> demo1 = null;
		Class<?> demo2 = null;
		Class<?> demo3 = null;
		//第一种方式,推荐使用这种方式
		try {
			demo1 = Class.forName("com.cctvjiatao.Reflect.Demo");
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
		//第二种方式,java语言中任何一个java对象都有getClass方法
		demo2 = new Demo().getClass();
		/*
		 第二种方式实质为以下代码
		Demo demo = new Demo();			//demo的运行时类是Demo
		Class demo2 = demo.getClass();	//demo2本身就是运行时类
		*/
		//第三种方式,java中每个类都有class属性
		demo3 = Demo.class;
		
		System.out.println("demo1的类名称:"+demo1.getName());
		System.out.println("demo2的类名称:"+demo2.getName());
		System.out.println("demo3的类名称:"+demo3.getName());
	}
}
【运行结果】:

demo1的类名称:com.cctvjiatao.Reflect.Demo
demo2的类名称:com.cctvjiatao.Reflect.Demo
demo3的类名称:com.cctvjiatao.Reflect.Demo

【实例3】通过Class实例化其他类对象

package com.cctvjiatao.Reflect;
public class Person {
	private String name;
	private int 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;
	}
	@Override
	public String toString() {
		return "["+this.name+"  "+this.age+"]";
	}
}
package com.cctvjiatao.Reflect;
/**
 * 通过Class实例化其他类对象
 **/
public class Hello {
	public static void main(String[] args) {
		Class<?> demo = null;
		try {
			demo = Class.forName("com.cctvjiatao.Reflect.Person");
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
		Person person = null;
		try {
			person = (Person)demo.newInstance();
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		}
		person.setName("可乐淘");
		person.setAge(26);
		System.out.println("Class<?>的实例demo:"+demo);
		System.out.println("Person的实例person:"+person);
	}
}
【运行结果】:

Class<?>的实例demo:class com.cctvjiatao.Reflect.Person
Person的实例person:[可乐淘  26]
但是注意一下,当我们把Person中的默认的无参构造函数取消的时候,比如自己定义只定义一个有参数的构造函数之后,会出现错误。比如我定义了一个构造函数:

public Person(String name, int age) {
        this.age=age;
        this.name=name;
    }
然后继续运行上面的程序,会出现:
java.lang.InstantiationException: com.cctvjiatao.Reflect.Person
	at java.lang.Class.newInstance(Class.java:364)
	at com.cctvjiatao.Reflect.Hello.main(Hello.java:15)
Exception in thread "main" java.lang.NullPointerException
	at com.cctvjiatao.Reflect.Hello.main(Hello.java:21)

所以大家以后再编写使用Class实例化其他类的对象的时候,一定要自己定义无参的构造函数

【实例4】通过Class调用其他类中的构造函数 (也可以通过这种方式通过Class创建其他类的对象)

package com.cctvjiatao.Reflect;
public class Person {
	private String name;
	private int age;
	public Person(){};
	public Person(String name){
		this.name = name;
	}
	public Person(int age){
		this.age = age;
	}	
	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;
	}
	@Override
    public String toString(){
        return "["+this.name+"  "+this.age+"]";
    }
}
package com.cctvjiatao.Reflect;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public class Hello {
	public static void main(String[] args) {
		Class<?> demo = null;
		try {
			demo = Class.forName("com.cctvjiatao.Reflect.Person");
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
		Person p1 = null;
		Person p2 = null;
		Person p3 = null;
		Person p4 = null;
		//取得全部的构造函数
		Constructor<?> con[] = demo.getConstructors();
		try {
			p1 = (Person) con[0].newInstance();
			p2 = (Person) con[1].newInstance("可乐淘");
			p3 = (Person) con[2].newInstance(26);
			p4 = (Person) con[3].newInstance("可乐淘",26);
		} catch (InstantiationException | IllegalAccessException | IllegalArgumentException
				| InvocationTargetException e) {
			e.printStackTrace();
		}
		System.out.println(p1);
		System.out.println(p2);
		System.out.println(p3);
		System.out.println(p4);		
	}
}
【运行结果】:

java.lang.IllegalArgumentException: wrong number of arguments
	at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
	at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
	at java.lang.reflect.Constructor.newInstance(Unknown Source)
	at com.cctvjiatao.Reflect.Hello.main(Hello.java:20)
[null  0]
null
null
null
在Hello.java中加入如下代码测试:

for(int i=0; i<con.length; i++){
<span style="white-space:pre">	</span>System.out.println(con[i]);
}
修改后的Hello.java代码如下:

package com.cctvjiatao.Reflect;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public class Hello {
	public static void main(String[] args) {
		Class<?> demo = null;
		try {
			demo = Class.forName("com.cctvjiatao.Reflect.Person");
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
		/*Person p1 = null;
		Person p2 = null;
		Person p3 = null;
		Person p4 = null;*/
		//取得全部的构造函数
		Constructor<?> con[] = demo.getConstructors();
		/*try {
			p1 = (Person) con[0].newInstance();
			p2 = (Person) con[1].newInstance("可乐淘");
			p3 = (Person) con[2].newInstance(26);
			p4 = (Person) con[3].newInstance("可乐淘",26);
		} catch (InstantiationException | IllegalAccessException | IllegalArgumentException
				| InvocationTargetException e) {
			e.printStackTrace();
		}
		System.out.println(p1);
		System.out.println(p2);
		System.out.println(p3);
		System.out.println(p4);*/		
		for(int i=0; i<con.length; i++){
			System.out.println(con[i]);
		}
	}
}
【运行结果】:
public com.cctvjiatao.Reflect.Person()
public com.cctvjiatao.Reflect.Person(java.lang.String,int)
public com.cctvjiatao.Reflect.Person(int)
public com.cctvjiatao.Reflect.Person(java.lang.String)
可见,是调用的构造器顺序有误,只需调整Hello.java中的如下代码:

p1 = (Person) con[0].newInstance();
p2 = (Person) con[1].newInstance("可乐淘",26);
p3 = (Person) con[2].newInstance(26);
p4 = (Person) con[3].newInstance("可乐淘");

修改后的Hello.java如下:

package com.cctvjiatao.Reflect;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public class Hello {
	public static void main(String[] args) {
		Class<?> demo = null;
		try {
			demo = Class.forName("com.cctvjiatao.Reflect.Person");
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
		Person p1 = null;
		Person p2 = null;
		Person p3 = null;
		Person p4 = null;
		//取得全部的构造函数
		Constructor<?> con[] = demo.getConstructors();
		try {
			p1 = (Person) con[0].newInstance();
			p2 = (Person) con[1].newInstance("可乐淘",26);
			p3 = (Person) con[2].newInstance(26);
			p4 = (Person) con[3].newInstance("可乐淘");
		} catch (InstantiationException | IllegalAccessException | IllegalArgumentException
				| InvocationTargetException e) {
			e.printStackTrace();
		}
		System.out.println(p1);
		System.out.println(p2);
		System.out.println(p3);
		System.out.println(p4);		
	}
}

【运行结果】:
[null  0]
[可乐淘  26]
[null  26]
[可乐淘  0]

【实例5】返回一个类实现的接口

package com.cctvjiatao.Reflect;
public interface Human {
	public static final String name = "可乐淘";
	public static int age = 20;
	public void sayChina();
	public void sayHello(String name, int age);
}
package com.cctvjiatao.Reflect;
public class Person implements Human {
	private String sex;
	public Person(){};
	public Person(String sex){
		this.sex = sex;
	}
	public String getSex() {
		return sex;
	}
	public void setSex(String sex) {
		this.sex = sex;
	}
	@Override
	public void sayChina() {
		System.out.println("hello,Human!");
	}
	@Override
	public void sayHello(String name, int age) {
		System.out.println(name+"  "+age);
	}
}
package com.cctvjiatao.Reflect;
public class Hello {
	public static void main(String[] args) {
		Class<?> demo = null;
		try {
			demo = Class.forName("com.cctvjiatao.Reflect.Person");
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
		//取得全部的接口
		Class<?> inter[] = demo.getInterfaces();
		for(int i=0; i<inter.length; i++){
			System.out.println("实现的接口:"+inter[i].getName());
		}
	}
}
【运行结果】:实现的接口:com.cctvjiatao.Reflect.Human

【实例6】取得其他类中的父类

Person.java代码同【实例5】,此处不在重复

package com.cctvjiatao.Reflect;
public class Hello {
	public static void main(String[] args) {
		Class<?> demo = null;
		try {
			demo = Class.forName("com.cctvjiatao.Reflect.Person");
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
		//取得父类
		Class<?> temp = demo.getSuperclass();
		System.out.println("Person类继承的父类为:"+temp.getName());
	}
}
【运行结果】:Person类继承的父类为:java.lang.Object

【实例7】获得其他类中的全部构造函数

Person.java代码同【实例5】,此处不在重复

package com.cctvjiatao.Reflect;
import java.lang.reflect.Constructor;
public class Hello {
	public static void main(String[] args) {
		Class<?> demo = null;
		try {
			demo = Class.forName("com.cctvjiatao.Reflect.Person");
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
		Constructor<?> con[] = demo.getConstructors();
		for(int i=0; i<con.length; i++)
		System.out.println("构造方法:"+con[i]);
	}
}

【运行结果】:
构造方法:public com.cctvjiatao.Reflect.Person(java.lang.String)
构造方法:public com.cctvjiatao.Reflect.Person()

【实例8】获得其他类中的构造函数的详细参数列表

Person.java代码同【实例5】,此处不在重复

package com.cctvjiatao.Reflect;
import java.lang.reflect.Constructor;
import java.lang.reflect.Modifier;
public class Hello {
	public static void main(String[] args) {
		Class<?> demo = null;
		try {
			demo = Class.forName("com.cctvjiatao.Reflect.Person");
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
		//获取所有构造方法
		Constructor<?> cons[] = demo.getConstructors();
		System.out.println("Person类的构造方法包括:");
		//打印出构造方法的前缀
		for(int i=0; i<cons.length; i++){
			Constructor con = cons[i];//取出第i个构造方法
			System.out.print(Modifier.toString(con.getModifiers()));//打印该构造方法的前缀修饰符
			System.out.print(" "+con.getName()+"(");//打印该构造方法的名称
			Class[] parameterTypes = con.getParameterTypes();//构造方法参数集,但是 数组类型显示特殊
			for(int j=0; j<parameterTypes.length; j++){
				System.out.print(parameterTypes[j].getName());
			}
			System.out.println(")");
		}
	}
}

【运行结果】:Person类的构造方法包括:
public com.cctvjiatao.Reflect.Person(java.lang.String)
public com.cctvjiatao.Reflect.Person()

【实例9】取得其他类的全部属性,也就是通过class取得一个类的全部框架

Person.java代码同【实例5】,此处不在重复

package com.cctvjiatao.Reflect;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
public class Hello {
	public static void main(String[] args) {
		Class<?> demo = null;
		try {
			demo = Class.forName("com.cctvjiatao.Reflect.Person");
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
		System.out.println("===============本类属性========================");
		//获取本类的所有属性
		Field[] field = demo.getDeclaredFields();
		for(int i=0; i<field.length; i++){
			//权限修饰符
			int mo = field[i].getModifiers();
			String priv = Modifier.toString(mo);
			//属性类型
			Class<?> type = field[i].getType();
			System.out.println(priv + " " + type.getName()+" "+field[i].getName()+";");
		}
		System.out.println("===============实现的接口或者父类的属性========================");
		//取得实现的接口或者父类的属性
		Field[] fieldParent = demo.getFields();
		for(int i=0; i<fieldParent.length; i++){
			//权限修饰符
			int mo = fieldParent[i].getModifiers();
			String priv = Modifier.toString(mo);
			//属性类型
			Class<?> type = fieldParent[i].getType();
			System.out.println(priv + " " + type.getName()+" "+fieldParent[i].getName()+";");
		}
	}
}
【运行结果】:

===============本类属性========================
private java.lang.String sex;
===============实现的接口或者父类的属性========================
public static final java.lang.String name;
public static final int age;

【实例10】通过反射调用其他类中的方法

Person.java代码同【实例5】,此处不在重复

package com.cctvjiatao.Reflect;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class Hello {
	public static void main(String[] args) {
		Class<?> demo = null;
		try {
			demo = Class.forName("com.cctvjiatao.Reflect.Person");
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
		try {
			//调用Person类中的sayChina方法
			Method method = demo.getMethod("sayChina");
			method.invoke(demo.newInstance());
			//调用Person类中的sayHello方法
			method = demo.getMethod("sayHello", String.class, int.class);
			method.invoke(demo.newInstance(), "可乐淘",26);
		} catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | InstantiationException e) {
			e.printStackTrace();
		}
	}
}
【运行结果】:
hello,Human!
可乐淘  26

【实例11】调用其他类的setget方法

Person.java代码同【实例5】,此处不在重复

package com.cctvjiatao.Reflect;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class Hello {
	public static void main(String[] args) {
		Class<?> demo = null;
		Object obj = null;
		try {
			demo = Class.forName("com.cctvjiatao.Reflect.Person");
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
		try {
			obj = demo.newInstance();
		} catch (InstantiationException | IllegalAccessException e) {
			e.printStackTrace();
		}
		setter(obj,"Sex","男",String.class);
		getter(obj,"Sex");
	}
	/**
	 * @param obj 操作的对象
	 * @param att 操作的属性
	 */
	 
	private static void getter(Object obj, String att) {
		Method method;
		try {
			method = obj.getClass().getMethod("get"+att);
			System.out.println(method.invoke(obj));
		} catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
			e.printStackTrace();
		}
	}
	/**
	 * @param obj 操作的对象
	 * @param att 操作的属性
	 * @param value 操作的属性
	 * @param type 操作的属性
	 */
	private static void setter(Object obj, String att, Object value, Class<?> type) {
		try {
			Method method = obj.getClass().getMethod("set"+att, type);
			method.invoke(obj, value);
		} catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
			e.printStackTrace();
		}
	}
}
【运行结果】:男

【实例12】通过反射操作属性

Person.java代码同【实例5】,此处不在重复

package com.cctvjiatao.Reflect;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class Hello {
	public static void main(String[] args) {
		Class<?> demo = null;
		Object obj = null;
		try {
			demo = Class.forName("com.cctvjiatao.Reflect.Person");
			obj = demo.newInstance();
			Field field = demo.getDeclaredField("sex");
			field.setAccessible(true);
			field.set(obj, "男");
			System.out.println(field.get(obj));
		} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | NoSuchFieldException | SecurityException e) {
			e.printStackTrace();
		}
		
	}
	
}
【运行结果】:

【实例13】通过反射取得并修改数组的信息

package com.cctvjiatao.Reflect;
import java.lang.reflect.Array;
public class Hello {
	public static void main(String[] args) {
		int[] temp = {1,2,3,4,5};
		Class<?> demo = temp.getClass().getComponentType();
		System.out.println("数组类型:"+demo.getName());
		System.out.println("数组长度:"+Array.getLength(temp));
		System.out.println("数组的第一个元素:"+Array.get(temp,0));
		Array.set(temp, 0, 100);
		System.out.println("修改之后数组第一个元素为:"+Array.get(temp,0));
	}
}
【运行结果】:

数组类型:int
数组长度:5
数组的第一个元素:1
修改之后数组第一个元素为:100

【实例14】通过反射修改数组大小

package com.cctvjiatao.Reflect;
import java.lang.reflect.Array;
public class Hello {
	public static void main(String[] args) {
		int[] temp = {1,2,3,4,5,6,7,8,9};
		int[] newTemp = (int[]) arrayInc(temp,15);
		print(newTemp);
		System.out.println("=========================");
		String[] atr = {"a","b","c"};
		String[] str = (String[]) arrayInc(atr,8);
		print(str);
	}
	public static Object arrayInc(Object obj, int len){
		Class<?> arr = obj.getClass().getComponentType();
		Object newArr = Array.newInstance(arr, len);
		int co = Array.getLength(obj);
		System.arraycopy(obj,0,newArr,0,co);
		return newArr;
	}
	public static void print(Object obj){
		Class<?> c = obj.getClass();
		if(!c.isArray()){
			return;
		}
		System.out.println("数组长度为:"+Array.getLength(obj));
		for(int i=0; i<Array.getLength(obj); i++){
			System.out.print(Array.get(obj, i)+" ");
		}
	}
}
【运行结果】:
数组长度为:15
1 2 3 4 5 6 7 8 9 0 0 0 0 0 0 =========================
数组长度为:8
a b c null null null null null 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值