Java反射学习(一)

Java反射学习


反射概念

• Java反射(Reflection)是一种新的操作类中成员变量、构造方法和普通方法的机制,为了实现对成员变量、构造方法和普通方法的操作,我们需要借助Java自身提供的java.lang包下的Class类和java.lang.reflect包下的反射API 。

单纯看这个概念可能比较抽象,我们从一般的情况说起:

普通的调用成员变量,构造方法、成员方法的 例子:
Java反射学习(一)_第1张图片
图中Test类里就是普通的调用成员变量,构造方法、成员方法的一种方式。而今天要学习的反射,就是调用成员变量、成员方法、构造方法的另一种方式。

Class类

要学习反射,就要先学习Class类。我们知道,类是一组对象抽取出来相同的属性和方法,而Class类相当于把不同的类中相同的属性和方法抽取出来,形成类的类。

概念理解

• Class类是Java 反射机制的入口,封装了一个类或接口的运行时信息,通过调用Class类的方法可以获取这些信息。

查看Class类的源码:
Java反射学习(一)_第2张图片
从源码中,我们可以读出一些信息:

  1. Class类由final修饰,意味着该类不可以被子类继承。
  2. 该类实现了Serializable接口;
  3. 该类的构造方法被private所修饰,即不能通过new关键字创建该类的对象,即如下的创建对象方式不可行:
    Java反射学习(一)_第3张图片

获取不同的Class类

  • 获取某一个自定义类对应的Class类实例化对象的三种方法:
package test;

import vo.Student;

public class Test {
	public static void main(String[] args) throws ClassNotFoundException {
		
		//方法一
		Class studentClass = Student.class;
		System.out.println("1、"+studentClass);
		
		//方法二
		studentClass = Class.forName("vo.Student");
		System.out.println("2、"+studentClass);
		
		//方法三
		studentClass = new Student().getClass();
		System.out.println("3、"+studentClass);
	}
}

运行后输出;
Java反射学习(一)_第4张图片
其中的StudentClass代表的就是Student这个类。

  • 获取数组类型的Class类:
package test;

import vo.Student;

public class Test {
	public static void main(String[] args) throws ClassNotFoundException {
		
		String [] names = {};
		Class arrayClass = String[].class;
		System.out.println(arrayClass);
	}	
}

输出:
在这里插入图片描述

  • 获取基本类型数据的Class类:
    通过包装类.TYPE获取Class类实例,当然,也可以通过基本数据类型.class获取Class类实例。
    这里通过int(Integer)来举例说明
public class Test {
	public static void main(String[] args) throws ClassNotFoundException {
		
		Class intClass = Integer.TYPE;
		System.out.println("1、"+intClass);
		
		intClass = Integer.class;
		System.out.println("2、"+intClass);
	}
}

运行后输出结果:
Java反射学习(一)_第5张图片
通过结果我们可以看出:
第一种方式获取到的是基本数据类型int
第二种方式获取到的是Integer这个类

  • 获取父类Class:
    使用getSuperclass()方法
public class Test {
	public static void main(String[] args) throws ClassNotFoundException {
		
		Class fatherClass = Student.class.getSuperclass();
		System.out.println(fatherClass);
	}
}

运行输出结果:
因为Student类的父类是Object类,所以输出为:
在这里插入图片描述
另一个更直观的例子:
Java反射学习(一)_第6张图片
输出结果为:
在这里插入图片描述

构造方法相关

1.获取构造方法

  • 获取public级别的构造方法
    使用Class类中的 getConstructors()方法,返回一个Constructor类型的数组。注意看控制台输出的构造方法的参数类型。第三个构造方法由于访问权限为private,所以没有输出。
  • 获取所有的构造方法
    使用Class类的getDeclaredConstructors()方法,返回一个Constructor类型的数组。
    Java反射学习(一)_第7张图片
    Student类:
package vo;

public class Student {
		
	public Student() {
		System.out.println("无参构造方法");
	}
	
	public Student(int age) {
		System.out.println("有参构造方法1");
	}
	
	private Student(String name) {
		System.out.println("有参构造方法2");
	}
}

Test类:

package test;

import java.lang.reflect.Constructor;

import vo.Student;

public class Test {
	public static void main(String[] args) throws ClassNotFoundException {
		
		//获取到对应的类
		Class studentClass = Student.class;
		
		//获取到一个类中所有public级别的构造方法
		Constructor [] constructors = studentClass.getConstructors();
		for (Constructor constructor : constructors) {
			System.out.println(constructor);
		}
		
		System.out.println("-------------------------------------");
		
		//忽略访问权限,获取到一个类中所有构造方法
		constructors = studentClass.getDeclaredConstructors();
		for (Constructor constructor : constructors) {
			System.out.println(constructor);
		}
	}
}
  • 根据参数不同获取不同的构造方法
    注意参数要写为基本数据类型.TYPE类.class
    Java反射学习(一)_第8张图片
    注意: 这里将Student类的方法访问权限都改成了pulic级别,如果是访问级别为private,则要将方法改为getDeclaredConstructor().如下图所示,其中也包括了getConstructor()方法访问私有成员方法报错的情况。
    Java反射学习(一)_第9张图片
    Test类:
package test;

import java.lang.reflect.Constructor;

import vo.Student;

public class Test {
	public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, SecurityException {
		
		//获取到对应的类
		Class studentClass = Student.class;
		
		Constructor constructor0 = studentClass.getDeclaredConstructor();
		System.out.println(constructor0);
		
		System.out.println("-------------------------------");
		
		Constructor constructor1 = studentClass.getDeclaredConstructor(Integer.TYPE);
		System.out.println(constructor1);
		
		System.out.println("*******************************");
		
		//这个方法没有改成getDeclaredConstructor,因为无法找到第2个有参构造方法所以报错
		Constructor constructor2 = studentClass.getConstructor(Integer.TYPE,String.class);
		System.out.println(constructor2);
	
	}
}

2.查看类的构造方法信息

  • 查看属于哪个类:
    使用Constructor类的getDeclaringClass()方法,然后用getName()获取。
    Java反射学习(一)_第10张图片
  • 获取构造方法名
    使用getName()方法
    Java反射学习(一)_第11张图片
  • 获取修饰符

Java反射学习(一)_第12张图片

  • 注意getModifiers()方法的返回值是int类型
    Java反射学习(一)_第13张图片
    源代码:
package test;

import java.lang.reflect.Constructor;
import java.lang.reflect.Modifier;

import vo.Student;

public class Test {
	public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, SecurityException {
		
		//获取到对应的类
		Class studentClass = Student.class;
		
		//获取到一个构造方法
		Constructor constructor = studentClass.getDeclaredConstructor();
		
		//构造方法属于哪一个类
		String ClassName = constructor.getDeclaringClass().getName();
		System.out.println(ClassName);
		
		//获取构造方法名
		String constructorName = constructor.getName();
		System.out.println(constructorName);
		
		//获取构造方法修饰符
		int result = constructor.getModifiers();
		String m = Modifier.toString(result);
		System.out.println(m);
		
	}
}
  • 查看参数列表
    使用getParameterTypes()方法
    Java反射学习(一)_第14张图片

3.反射调用构造方法

  • 调用public级别的构造方法
    使用Constructor类的newInstance(…)方法,括号内为对应的参数。使用不同的参数列表来找到相应的构造方法。

如代码:

Object obj = constructor.newInstance(12,"Tom");

Java反射学习(一)_第15张图片
如上图,创建的obj相当于一个Student对象(属于上转型对象)。根据参数执行了有参构造方法2。

注意出现异常后都抛出
Java反射学习(一)_第16张图片

  • 调用private级别的构造方法
    在调用前使用setAccessible()方法:

Java反射学习(一)_第17张图片
代码:

public class Test {
	public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
		
		//获取到对应的类
		Class studentClass = Student.class;
		
		//获取到构造方法
		Constructor constructor = studentClass.getDeclaredConstructor(Integer.TYPE);
		Constructor constructor1 = studentClass.getDeclaredConstructor(Integer.TYPE,String.class);
		
		//调用构造方法
		Object obj = constructor.newInstance(12);
		
		//忽略访问权限
		constructor1.setAccessible(true);
		Object obj1 = constructor1.newInstance(12,"Tom");
	}
}

你可能感兴趣的:(Java反射学习(一))