黑马程序员java自学总结之--反射

------- android培训java培训、期待与您交流! ----------

1.什么是反射?

反射就是把java类中的成员映射成不同的java类。

2.Class

我们编写的java程序是由java类构成,那么这个java类是如何得到的,java虚拟机会对我们的代码进行编译,会在硬盘上生成一个.class的文件,这个文件是类的字节码文件,我们在程序中使用的类都的先把这个文件加载到内存中去才可以去生成对象等操作,通过Class这个类同样可以产生对象。

示例:根据类名得到一个类的字节码文件

Class claszz  = Class.forName("java.lang.String");

这时我们可以得到一个String类的字节码文件,同样使用这个文件我们可以得到对象等得到类的所有,因为反射操作的就是一个类的所有成员。

示例程序:

public static void main(String[] args) throws ClassNotFoundException {
		Class cls1 = Person.class;//Class生成要得到这个类的字节码。
		Class cls2 = Class.forName("java.lang.String");//若虚拟机中加载了该类并有了该类的字节码,直接得到,若没有加载,就重新加载得到。
		
		//得到字节码的三种方式
		String str = "abc";
		Class c1 = str.getClass();//通过对象得到字节码
		Class c2 = String.class;//通过类的到字节码
		Class c3 = Class.forName("java.lang.String");//通过完整类名得到字节码
		System.out.println(c1==c2);
		System.out.println(c2==c3);
		System.out.println(c1.isPrimitive());
		//只要是在源程序中出现的类型,都有对应的class实例对象
	}

class Person
{
	
}
}
 反射就是把java类中的各种成分映射成相应的java类。Construct类代表某个类中的构造方法。得到某个类的所有构造方法getConstructs();得到一个单独的构造getConstruct();

示例程序:

public class Demo3 {
	public static void main(String[] args) throws NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchFieldException {
		Constructor c1 = String.class.getConstructor(StringBuffer.class);
		//想要new String(new StringBuffer())
		String str = (String)c1.newInstance(new StringBuffer("abc"));
		System.out.println(str);
		//Class中也有newinstance方法,简练使用,
		/*成员变量的反射
		 * Field类
		 * */
		Person1 p1 = new Person1("小叶",20);
		Field f1 = p1.getClass().getDeclaredField("name");
		//f1的值是多少?不是5,f1不是对象身上的变量,而是类上,要用他得到对象的值
		f1.setAccessible(true);//抢。暴力反射。
		System.out.println(f1.get(p1));
	}
}
class Person1
{
	public Person1(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	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 "Person [name=" + name + ", age=" + age + "]";
	}
	
}

注意:这里使用了构造方法来产生一个对象,在字节码对象Class中也有一个得到对象的方法,其实它是为了操作简单,底层还是使用的无参数的构造函数。

练习:把一个对象的所有字符串成员的值得包含b的改为a

	public static void main(String[] args) throws IllegalArgumentException, IllegalAccessException {
		ReflectPoint rp = new ReflectPoint(3,5);
		Field[] fs = rp.getClass().getDeclaredFields();
		for(Field f:fs)
		{
			if(f.getType() == String.class)//对字节码用等号比,因为是同一份字节码
			{
				String strValue = (String)f.get(rp);
				String newValue = strValue.replaceAll("b", "a");
				f.set(rp, newValue);
			}
		}
		System.out.println(rp.str1+":"+rp.str2+":"+rp.str3);
	}

}
class ReflectPoint
{
	public ReflectPoint(int x, int y) {
		super();
		this.x = x;
		this.y = y;
	}
	private int x;
	private int y;
	public String str1 = "ball";
	public String str2 = "basketball";
	public String str3 = "itcast";
	
}

Method类

Method类Method类代表某个类中的一个成员方法得到一个类的某一个方法 Method charAt = Class.forName("java.lang.String").getMethod("charAt",int.calss) 调用方法通常方法:str.charAt(1);反射方式:charAt.invoke(str,1);

public static void main(String[] args) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
        String str = new String("abc");
        Method charAt = str.getClass().getMethod("charAt", int.class);
        System.out.println(charAt.invoke(str, 1));
        //如果invoke的第一个参数为null则这个方法是一个静态方法
        
        
        
    }

练习:写一个程序,这个程序能够根据用户提供的类名,去执行该类中的main方法

public class Demo6 {
	public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
		Class c1 = Class.forName("com.ccsu.reflection.TestArg");
		Method m1 = c1.getMethod("main",String[].class);
		//System.out.println(m1.invoke(null,new String[] {"fsdf","3","78"}));//异常:参数的类型不对
		//上面java认为受到了三个参数。jdk 此时认为数组是几个Object
		//方法1
		System.out.println(m1.invoke(null, new Object[] {new String[] {"fsdf","3","78"}}));
		//方法2
		System.out.println(m1.invoke(null,(Object)new String[] {"fsdf","3","78"}));
	}
}
class TestArg
{
	public static void main(String[] args) {
		for(String s:args)
		{
			System.out.println(s);
		}
	}
}

数组的反射


具有相同维数和元素类型的数组属于同一个类型,即具有相同的Class实例对象
代表数组的Class实例对象的getSuperClass方法返回的父类为Object类对应的Class
 基本类型的一维数组可以被当做Object类型使用,不能当做Object[]类型使用,非基本类型的一维数组,
 既可以当做Object类型使用,又可以当做Object[] 类型使用
Arrays.asList方法处理int[] 和String[] 时的差异

public static void main(String[] args) {
		int[] a1 = {2,3,4};
		int[] a2 = new int[4];
		int[][] a3 = new int[2][3];
		String[] str = new String[4];
		System.out.println(a1.getClass() == a2.getClass());
		//数组的维数相同,得到的字节码是同一份。
		System.out.println(a1.getClass().getName());
		//System.out.println(a1.getClass() == a3.getClass());
		System.out.println(a1.getClass().getSuperclass().getName());
		//一维数组的父类都是Object
		//所以
		Object o1 = a1;
		
		
		//对数组进行反射,没有办法得到整个数组元素的类型,可以得到某一个元素的类型来得到整体的类型
		//使用类Array来操作,一个打印方法
		printArray(a1);
		printArray(str);
		
		
		
		
	}
	public static void printArray(Object obj)
	{
		Class clazz = obj.getClass();
		if(clazz.isArray())
		{
			int len = Array.getLength(obj);
			for (int i = 0; i < len; i++) {
				System.out.println(Array.get(obj, i));
			}
		}else
		{
			System.out.println(obj);
		}
	}
}

编写一个小框架程序,从配置文件中读取类的信息,通过反射来执行

public static void main(String[] args) throws IOException, InstantiationException, IllegalAccessException, ClassNotFoundException {
//hashCode方法的作用,对对象进行计算,当修改对象后hashcode会改变,再去操作会内存泄露
	//小框架书写
		FileInputStream fis = new FileInputStream("test.properties");
		Properties p = new Properties();
		p.load(fis);
		fis.close();
		String className = p.getProperty("className");
		System.out.println(className);
		Collection c = (Collection)Class.forName(className).newInstance();
		PersonDemo p1 = new PersonDemo("小叶",20);
		PersonDemo p2 = new PersonDemo("小李",25);
		PersonDemo p3 = new PersonDemo("小王",24);
		PersonDemo p4 = new PersonDemo("小叶",20);
		PersonDemo p5 = new PersonDemo("小叶",20);
		c.add(p4);
		c.add(p3);
		c.add(p2);
		c.add(p1);
		c.add(p5);
		System.out.println(c.size());
	}

}
class PersonDemo
{
	public PersonDemo(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	@Override
	public boolean equals(Object obj)
	{
		if(!(obj instanceof Person))
			return false;
		PersonDemo p = (PersonDemo)obj;
			if(this.name == p.name && this.age == p.age)
			{
				return true;
			}
			else
				return false;
	}
	public int hashCode() {
		
		return name.hashCode();
	}
	@Override
	public String toString() {
		return "Person [name=" + name + ", age=" + age + "]";
	}
	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;
	}
}


1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值