反射(上)——反射的引入、反射调用构造方法

反射

1. 反射的引入

//正向操作(根据类new出对象)
class Test1 {
	public static void main(String[] args) {
		Date date = new Date();
		System.out.println(date);
	}
}

在之前我们一直使用的是 new类名()来获取对象,即在上例中所谓的“正向操作”。那么我们如何根据对象来获取对象的信息呢,接下来我们就将引入反射机制。

反射:即根据已有类的对象反推类的组成,是所有Java框架的基础,没有反射就没有JavaEE框架。“反”指的是根据对象来获取对象的来源信息,此操作核心在于Object类的的一个方法:getClass()方法:获取Class对象

class与Class:

class:定义类的关键字。

Class:(class Class)是一个类,描述具体类的组成信息。Class类由JVM产生,当类加载的时候,JVM会产生该类的唯一Class类对象。

类加载过程:反射的基本原理与Class对象

          

class Test1 {
	public static void main(String[] args){
		Date date1 = new Date();
		Date date2 = new Date();
		System.out.println(date1.getClass() == date2.getClass());
	}
}
运行结果:true(因为是由同一个类产生的对象)

2. 反射的使用

(1)获取Class对象的三种方式

a. 使用Object类的getClass()方法获取当前对象的Class实例

b. 使用类的class属性(任何数据类型(包括基本数据类型)都有一个静态的class属性)

c. 调用Class对象的静态方法:forName(类的全名称”)

在运行期间,一个类只有一个Class对象产生。

/*
 * 获取Class对象的三种方式(以Date类为例)
 * */
public class Test1{
	public static void main(String[] args) {
		//new后产生一个Date()对象和一个Class对象
		Date date = new Date();
		//1.使用Object类的getClass()方法获取当前对象的Class实例
		Class<?> class1 = date.getClass();
		System.out.println(class1.getName());
		
		//2.使用类的class属性获取当前对象的Class实例
		Class<?> class2 = Date.class;
		//判断第一种方式获取的Class对象是否和本次获取的为同一对象
		System.out.println(class1.getName() ==class2.getName());
		
		//3.调用Class对象的静态方法:forName(“类的全名称”)获取当前对象的Class实例
		try {
			//方法中的字符串必须是真实名称带包名的类路径,即 包名.类名
			Class<?> class3 = Class.forName("java.util.Date");
			//判断第二次获取的Class对象是否和本次获取的为同一对象
			System.out.println(class2.getName() == class3.getName());
			
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
	}
}

                   

(2)利用反射创建对象

创建对象的方式:

     正向处理:利用new 类名( ) 操作。

     反射处理:利用Class对象的newInstance()操作。

public class Test1{
	public static void main(String[] args) {
		//正向创建对象
		Date date1 = new Date();
		System.out.println(date1);
		//获取Class对象
		Class<?> class1 = date1.getClass();
		try {
			//通过反射进行类实例化对象的创建
			Object object = class1.newInstance();
			System.out.println(object);
		} catch (InstantiationException | IllegalAccessException e) {
			e.printStackTrace();
		}
	}
}

                       

3. 反射与类操作

利用反射可以做出一个对象的所有操作行为,关键是这一切都基于Object进行。

(1)取得父类信息

Java中任何类都有父类,在Class类中就可以通过如下方式得到父类或实现的父接口信息。

a. 取得包名称:public Package getPackage() 方法

b. 取得父类信息:public native Class<?> super <? super T> getSuperclass()

c. 取得所有父接口信息:public Class<?> [ ] getInterfaces()

/*
 * 反射与类操作
 * */
//取得父类信息
interface IFruit{}
interface IMessage{}
class Apple1 {}
class Apple extends Apple1 implements IFruit,IMessage{}
public class Test1{
	public static void main(String[] args) {
		//取得Apple对象
		Class<?> class1 = Apple.class;
		System.out.println(class1.getName());
		//取得包名(返回值为package类型)  class.包名
		Package package1 = class1.getPackage();
		System.out.println("包名: "+ package1.getName());
		//取得父类信息(返回值仍为Class)
		Class<?> superClassName =  class1.getSuperclass();
		System.out.println("父类:"+ superClassName.getName());
		//取得所有接口信息(返回值为Class数组)
		Class<?> [] classes = class1.getInterfaces();
		for(Class<?> class0:classes) {
			System.out.println("接口: "+ class0.getName());
		}
 	}
}

                            

(2)反射调用构造方法

一个类中可以有多个构造方法,我们可以使用Class类中的如下方来获取构造方法。

以下方法返回的类型都是java.lang.reect.Constructor类的实例化对象。

a. 取得指定参数的构造方法:

取得类中指定参数访权限为public的构造方法:

public Constructor<T> getConstructor(Class<?>... parameterTypes)

取得类中指定参数的构造方法(任意访问权限):

Public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)

 

b. 取得类中所有构造方法

取得类中所有访问权限为public的构造方法:

public Constructor<?>[] getConstructors() throws SecurityException

取得类中所有的构造方法(任意访问权限):

public Constructor<?>[] getDeclaredConstructors() throws SecurityException


//反射调用构造
class Person{
	private String name;
    int age;
    char gender;
    //默认的构造方法
    Person(String string){
    	System.out.println("默认构造方法"+string);
    }
    //无参构造方法
    public Person() {
		super();
		System.out.println("调用公有的无参构造");
	}
    //带一个参数的构造方法
    public Person(char gender) {
		super();
		this.gender = gender;
		System.out.println("调用公有的带一个参数的有参构造");
	}
    //带多个参数的构造方法
    public Person(String name, int age) {
		super();
		this.name = name;
		this.age = age;
		System.out.println("调用公有的带多个参数的有参构造");
	}
    //受保护的构造方法  
    protected Person(boolean n){  
        System.out.println("受保护的构造方法 n = " + n);  
        System.out.println("调用受保护的有参构造");
    } 
    //私有构造方法
	private Person(int age) {
		super();
		this.age = age;
		System.out.println("调用私有的有参构造");
	} 
}
public class Test1{
	public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, SecurityException {
		Class<?> class2 = Person.class;
		Object object = null;
		try {
			//默认调用类的无参构造,若不含有无参构造则会报错 java.lang.InstantiationException
			object = class2.newInstance();
			System.out.println(object);
		} catch (InstantiationException | IllegalAccessException e) {
			e.printStackTrace();
		}
		System.out.println();
		
		//通过Constructor类创建实例化对象
		//加载Class对象
		Class<?> class1 = Class.forName("reflect.Person");
		//取得类中指定参数访权限为public的构造方法
		Constructor<?> constructor = class1.getConstructor(String.class,int.class);
		System.out.println("\n**************获得访问权限为public的指定构造方法************\n");
		System.out.println(constructor);
		//取得类中指定参数的构造方法(任意访问权限)
		Constructor<?> constructor2 = class1.getDeclaredConstructor(boolean.class);
		System.out.println("\n**************获得任意访问权限的指定构造方法************\n");
		System.out.println(constructor2);
			//取得类中所有访问权限为public的构造方法
			Constructor<?> [] constructors = class1.getConstructors();
			System.out.println("\n**************获得访问权限为public的所有构造方法************\n");
			for (Constructor<?> constructor1 : constructors) {
				System.out.println(constructor1);
			}
		    //取得类中所有的构造方法(任意访问权限)
			Constructor<?> [] constructors2 = class1.getDeclaredConstructors();
			System.out.println("\n**************获得任意访问权限的所有构造方法************\n");
			for (Constructor<?> constructor1 : constructors2) {
				System.out.println(constructor1);
			}
		}
}

                  

以上的操作是直接利用了Constructor类中的toString()方法取得了构造方法的完整信息(包含方法权限,参数列 表),而如果你只使用了getName()方法,只会返回构造方法的包名.类名。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值