Java的基石—反射

反射是什么?
1.在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法、构造函数;
2.对于任意一个对象,都能够调用它的任意一个方法和属性;
这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制

问题一:
编写一个函数,可以接收一个类的全路径,输出该类的所有属性和方法。

问题二:
要求通过一个配置文件,创建Cat类的一个对象实例,并调用cry方法,怎么办?

1.通过反射查看类的信息
(1)每个类被加载后,系统都会为该类生成一个对应的Class对象,通过该Class对象就可以访问到JVM中的这个类。
(2)Java程序中获得Class对象通常有如下三种方式:
使用Class的forName()
调用某个类的class属性
调用某个对象的getClass()
(3)一旦获取了某个类的Class对象之后,程序就可以调用Class对象的方法来获得该对象和该类的真实信息了。

package com.reflection;

public class Test1 {

	public static void main(String[] args) throws ClassNotFoundException {
		// TODO Auto-generated method stub
		//得到Cat的Class对象
		//1.通过forName
		Class clazz1=Class.forName("com.reflection.Cat");
		//2.通过class属性
		Class clazz2=Cat.class;
		//3.通过Cat的对象实例,来获取
		Cat cat=new Cat();
		Class clazz3=cat.getClass();
		//这三个Class是同一个对象,我们来验证一下
		if(clazz1==clazz2) {
			System.out.println("ok1");
		}
		if(clazz2==clazz3) {
			System.out.println("ok2");
		}
	}

}

class Dog{
	
}

//class Cat{
//	private String name;
//}

class Brid{
	
}

一个类的创建原理:

在这里插入图片描述
2.使用反射生成对象
通过反射来生成对象有如下两种方式:
(1)使用Class对象的newInstance()方法创建Class对象对应类的实例,这种方式要求该Class对象的对应类有默认的构造器,而执行newInstance()方法时实际上是利用默认的构造器来创建该类的实例
(2)先使用使用Class对象获取指定的Constructor对象,再调用Constructor对象的newInstance()方法来创建该Class对象对应的实例。通过这种方式可以选择使用某个类的指定的构造器来创建实例。

package com.reflection;

import java.lang.reflect.Constructor;

public class Test2 {

	public static void main(String[] args) throws Exception {
		// TODO Auto-generated method stub
		// 得到Cat的Class对象
		// 1.通过forName
		Class clazz1 = Class.forName("com.reflection.Cat");
		//通过Class对象可以创建对象实例
//		Cat cat1=(Cat)clazz1.newInstance();
//		cat1.show();
		
		
		//通过public Cat(String name,int age)来创建实例
		//1.通过class对象来得到构造函数
		//构造函数有多个,要怎么知道调用哪一个呢?这样做就可以了String.class,int.class
		Constructor c1=clazz1.getConstructor(String.class,int.class);
		Cat cat1=(Cat)c1.newInstance("小猫",6);
//		cat1.show();
		
		//2.通过 public Cat(String[] foods)来创建实例
		Constructor c2=clazz1.getConstructor(String[].class);
		String[] foods= {"鱼","老鼠"};
		Cat cat2=(Cat)c2.newInstance((Object)foods);
		cat2.show();
		
	}

}



package com.reflection;

import java.util.List;

public class Cat {
//	public String name;
//	public int age;
	
	public String name="小猫咪";
	public int age;
	
	public String[] foods;
	public void show() {
		System.out.println("猫名"+name);
		for (int i = 0; i < foods.length; i++) {
			System.out.println(foods[i]);
		}
	}
	
	public Cat() {
		
	}
	
	public Cat(String[] foods) {
		this.foods=foods;
	}

	public void show(String name) {
		System.out.println("输入的名字是"+name);
	}
	
	public void show(String name,int age) {
		System.out.println("输入的名字是"+name+" 年龄是"+age);
	}
	
//	public void show(List list) {
//		for(int i=0;i<list.size();i++) {
//			System.out.println(list.get(i));
//		}
//	}
	
	private void show(List list) {
		for(int i=0;i<list.size();i++) {
			System.out.println(list.get(i));
		}
	}
	
	public Cat(String name,int age) {
		this.name=name;
		this.age=age;
	}
}

3.使用反射调用方法
(1)当获取某个类对应的Class对象后,就可以通过Class对象的getMethods()或getMethod()方法来获取全部方法或指定的方法。
(2)每个Method对象对应一个方法,获得Method对象后,程序就可通过该Method来调用对应方法。在Method里包含一个invoke()方法。

package com.reflection;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.*;


public class Test3 {
	//通过反射来获取和调用指定的方法!
	public static void main(String[] args) throws Exception {
		//public void show
		//1.通过反射创建Cat实例
		Class clazz1=Class.forName("com.reflection.Cat");
		//得到构造函数
		Constructor constructor=clazz1.getConstructor(String[].class);
		String[] foods= {"fish","mouse"};
		Cat cat1=(Cat) constructor.newInstance((Object)foods);
		//使用反射来调用show()
		//获取show方法
		//Method method=clazz1.getMethod("show", null);
//		Method method=clazz1.getMethod("show", String.class);
//		Method method=clazz1.getMethod("show", String.class,int.class);
		//调用invoke的第一个参数表示对象实例
//		method.invoke(cat1, "顺平",80);
		
//		Method method=clazz1.getMethod("show", List.class);
//		List list=new ArrayList();
//		list.add("abc");
//		list.add("中国");
//		method.invoke(cat1, list);
		
		
		//如何调用私有的函数,比如private void show(List list)
		Method method=clazz1.getDeclaredMethod("show", List.class);
		method.setAccessible(true);//暴力访问
		List list=new ArrayList();
		list.add("abc");
		list.add("999");
		method.invoke(cat1, list);
		
		}

}

4.使用反射访问属性值
(1)通过Class对象的getFields()或getField()方法可以获取该类所包括的全部Field或指定的Field
(2)Field通过如下两组方法来访问属性
get(Object obj)[字段类型是引用类型,用此法]
getXXX(Object obj)[字段类型是基本数据类型,用此法]
getXXX(Object obj,XXX val)

package com.reflection;

import java.lang.reflect.Field;

public class Test4 {

	public static void main(String[] args) throws Exception {
		// TODO Auto-generated method stub
		//需求:通过反射,获取Cat类的name属性值
		//1.得到Class对象,创建实例
		Class clazz1=Class.forName("com.reflection.Cat");
		Cat cat1=(Cat)clazz1.newInstance();
		cat1.setName("悟空");//如果这里把名字改成悟空呢?
		//通过clazz1,获取cat1对象的属性name
		Field field=clazz1.getField("name");
		
		//通过field来得到值,传统的方法是:cat1.getValue('name'),但反射是反着来的
		String nameVal=(String)field.get(cat1);
		System.out.println("名字是"+nameVal);
	}

}



package com.reflection;

import java.util.List;

public class Cat {
//	public String name;
//	public int age;
	
	public String name="小猫咪";
	
	public void setName(String name) {
		this.name = name;
	}

	public int age;
	
	public String[] foods;
	public void show() {
		System.out.println("猫名"+name);
		for (int i = 0; i < foods.length; i++) {
			System.out.println(foods[i]);
		}
	}
	
	public Cat() {
		
	}
	
	public Cat(String[] foods) {
		this.foods=foods;
	}

	public void show(String name) {
		System.out.println("输入的名字是"+name);
	}
	
	public void show(String name,int age) {
		System.out.println("输入的名字是"+name+" 年龄是"+age);
	}
	
//	public void show(List list) {
//		for(int i=0;i<list.size();i++) {
//			System.out.println(list.get(i));
//		}
//	}
	
	private void show(List list) {
		for(int i=0;i<list.size();i++) {
			System.out.println(list.get(i));
		}
	}
	
	public Cat(String name,int age) {
		this.name=name;
		this.age=age;
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值