在 Object 类中定义了以下的方法,此方法将被所有子类继承
public final native Class<?> getClass();
以上方法返回值的类型是一个 Class 类,此类是Java反射的源头,实际上所谓反射从程序的运行结果来看也很好理解,即可以通过对象反射求出类的名称。
对象照镜子后可以得到的信息:某个类的属性、方法和构造器、某个类到底实现了哪些接口。对于每个类而言,JRE都为其保留一个不变的Class类型的对象。一个Class对象包含了特定某个结构的有关信息。
方法名 | 功能说明 |
---|---|
static ClassforName(String name) | 返回指定类名name的Class对象 |
Object newInstance() | 调用无参构造函数,返回Class对象的一个实例 |
getName() | 返回此Class对象所表示的实体(类、接口、数组类或void)的名称 |
Class getSuperClass() | 返回当前Class对象的父类的Class对象 |
Class[] getInterfaces() | 返回当前Class对象的接口 |
ClassLoader getClassLoader() | 返回该类的类加载器 |
Constructor[] getConstructors() | 返回一个包含某些Constructor对象的数组 |
Method getMothed(String name, Class.. T) | 返回一个Method对象,此对象的形参类型为paramType |
Field[] getDeclaredFields() | 返回Field对象的一个数组 |
Class c1 = User.class;
User user = new User();
Class c2 = user.getClass();
Class c3 = Class.forName("com.ray.pojo.User");
类型.Type
。Class c4 = Integer.TYPE;
示例
public class Person {
public String name;
}
public class Student extends Person {
public Student() {
this.name = "学生";
}
}
public class Demo03 {
public static void main(String[] args) throws ClassNotFoundException {
Person person = new Student();
System.out.println("这个人是: " + person.name);
// 方式一:通过对象获取
Class c1 = person.getClass();
System.out.println("c1.hashCode() = " + c1.hashCode());
// 方式二:forName获取
Class c2 = Class.forName("com.ray.pojo.Student");
System.out.println("c2.hashCode() = " + c2.hashCode());
// 方式三:通过类名.class获取
Class c3 = Student.class;
System.out.println("c3.hashCode() = " + c3.hashCode());
// 方式四:基本内置类型的包装类都有一个Type类型
Class c4 = Integer.TYPE;
System.out.println("c4 = " + c4);
// 获得父类类型
Class c5 = c1.getSuperclass();
System.out.println("c5 = " + c5);
}
}
结果
这个人是: 学生
c1.hashCode() = 460141958
c2.hashCode() = 460141958
c3.hashCode() = 460141958
c4 = int
c5 = class com.ray.pojo.Person
public class Demo04 {
public static void main(String[] args) {
Class c1 = Object.class; // 类
Class c2 = Comparable.class; // 接口
Class c3 = String[].class; // 一维数组
Class c4 = int[][].class; // 二维数组
Class c5 = Override.class; // 注解
Class c6 = ElementType.class; // 枚举
Class c7 = Integer.class; // 基本数据类型
Class c8 = void.class; // void
Class c9 = Class.class; // Class
System.out.println(c1);
System.out.println(c2);
System.out.println(c3);
System.out.println(c4);
System.out.println(c5);
System.out.println(c6);
System.out.println(c7);
System.out.println(c8);
System.out.println(c9);
}
}
结果
class java.lang.Object
interface java.lang.Comparable
class [Ljava.lang.String;
class [[I
interface java.lang.Override
class java.lang.annotation.ElementType
class java.lang.Integer
void
class java.lang.Class
当程序主动使用某个类时,如果该类还未被加载到内存中,则系统会通过如下三个步骤来对该类进行初始化。
类的主动引用(一定会发生类的初始化)
类的被动引用(不会发生类的初始化)
package com.ray.demo;
/**
* @Description: 测试类什么时候会初始化
* @Author Administrator
* @Date 2020/9/5 11:53
* @Version 1.0
*/
public class Demo06 {
static {
System.out.println("Main类被加载");
}
public static void main(String[] args) throws ClassNotFoundException {
/**
* Main类被加载
* 父类被加载
* 子类被加载
* */
//Son son = new Son();
/**
* 反射也会产生主动引用
* Main类被加载
* 父类被加载
* 子类被加载
* */
//Class.forName("com.ray.demo.Son");
/**
* 不会产生类的引用的方法
* Main类被加载
* 父类被加载
* 2
* */
//System.out.println(Son.b);
/** Main类被加载 */
//Son[] array = new Son[5];
/**
* Main类被加载
* 1
* */
System.out.println(Son.A);
}
}
class Father {
static int b = 2;
static {
System.out.println("父类被加载");
}
}
class Son extends Father {
static {
System.out.println("子类被加载");
m = 300;
}
static int m = 100;
static final int A = 1;
}
package com.ray.demo;
/**
* @Description: 类加载器
* @Author Administrator
* @Date 2020/9/5 14:33
* @Version 1.0
*/
public class Demo07 {
public static void main(String[] args) throws ClassNotFoundException {
// 获取系统类的加载器
ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
System.out.println("systemClassLoader = " + systemClassLoader);
// 获取系统类加载器的父类加载器 -> 扩展类加载器
ClassLoader parent = systemClassLoader.getParent();
System.out.println("parent = " + parent);
// 获取扩展类加载器的父类加载器 -> 根加载器(无法直接获取)
ClassLoader parent1 = parent.getParent();
System.out.println("parent1 = " + parent1);
// 测试当前类是哪个加载器加载的
ClassLoader classLoader = Class.forName("com.ray.demo.Demo07").getClassLoader();
System.out.println("classLoader = " + classLoader);
// 测试JDK内置的类是谁加载的
classLoader = Class.forName("java.lang.Object").getClassLoader();
System.out.println("classLoader = " + classLoader);
// 如何获得系统类加载器可以加载的路径
//System.out.println(System.getProperty("java.class.path"));
}
}
结果
systemClassLoader = sun.misc.Launcher$AppClassLoader@18b4aac2
parent = sun.misc.Launcher$ExtClassLoader@1b6d3586
parent1 = null
classLoader = sun.misc.Launcher$AppClassLoader@18b4aac2
classLoader = null
package com.ray.demo;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
/**
* @Description: 获得类的信息
* @Author Administrator
* @Date 2020/9/5 14:39
* @Version 1.0
*/
public class Demo08 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException {
Class c1 = Class.forName("com.ray.pojo.User");
System.out.println("-------- 获取类的名字 ---------");
// 获取类的名字
System.out.println("c1.getName() = " + c1.getName()); // 获得包名 + 类名
System.out.println("c1.getSimpleName() = " + c1.getSimpleName()); // 获得类名
System.out.println("-------- 获得类的属性 - 只能找到 public 属性 ---------");
// 获得类的属性 - 只能找到 public 属性
Field[] fields = c1.getFields();
for (Field field : fields) {
System.out.println(field);
}
System.out.println("-------- 获得类的属性 - 能找到全部属性 ---------");
// 获得类的属性 - 能找到全部属性
Field[] declaredFields = c1.getDeclaredFields();
for (Field declaredField : declaredFields) {
System.out.println(declaredField);
}
System.out.println("-------- 获得指定属性的值 - 只能找到 public 属性 ---------");
// 获得指定属性的值 - 只能找到 public 属性
//Field name = c1.getField("name");
//System.out.println("name = " + name); // java.lang.NoSuchFieldException: name
System.out.println("-------- 获得指定属性的值 - 能找到全部属性 ---------");
// 获得指定属性的值 - 能找到全部属性
Field name = c1.getDeclaredField("name");
System.out.println("name = " + name);
System.out.println("-------- 获得类的方法 - 获得本类及其父类的public方法 ---------");
// 获得类的方法
Method[] methods = c1.getMethods();
for (Method method : methods) {
System.out.println("method = " + method);
}
System.out.println("-------- 获得类的方法 - 获得本类的所有方法 ---------");
Method[] declaredMethods = c1.getDeclaredMethods();
for (Method declaredMethod : declaredMethods) {
System.out.println("declaredMethod = " + declaredMethod);
}
System.out.println("-------- 获得类的指定方法 ---------");
// 添加参数可避免重载
Method getName = c1.getMethod("getName", null);
System.out.println("getName = " + getName);
Method method = c1.getMethod("setName", String.class);
System.out.println("method = " + method);
System.out.println("-------- 获得类的构造器 ---------");
// 只获得 public 构造方法
Constructor[] constructors = c1.getConstructors();
for (Constructor constructor : constructors) {
System.out.println("constructor = " + constructor);
}
// 获得本类的全部构造方法
Constructor[] declaredConstructors = c1.getDeclaredConstructors();
for (Constructor declaredConstructor : declaredConstructors) {
System.out.println("declaredConstructor = " + declaredConstructor);
}
// 获得指定构造方法
Constructor declaredConstructor = c1.getDeclaredConstructor(String.class, int.class, int.class);
System.out.println("++ declaredConstructor ++ = " + declaredConstructor);
}
}
结果
-------- 获取类的名字 ---------
c1.getName() = com.ray.pojo.User
c1.getSimpleName() = User
-------- 获得类的属性 - 只能找到 public 属性 ---------
-------- 获得类的属性 - 能找到全部属性 ---------
private java.lang.String com.ray.pojo.User.name
private int com.ray.pojo.User.id
private int com.ray.pojo.User.age
-------- 获得指定属性的值 - 只能找到 public 属性 ---------
-------- 获得指定属性的值 - 能找到全部属性 ---------
name = private java.lang.String com.ray.pojo.User.name
-------- 获得类的方法 - 获得本类及其父类的public方法 ---------
method = public java.lang.String com.ray.pojo.User.toString()
method = public java.lang.String com.ray.pojo.User.getName()
method = public int com.ray.pojo.User.getId()
method = public void com.ray.pojo.User.setName(java.lang.String)
method = public void com.ray.pojo.User.setAge(int)
method = public void com.ray.pojo.User.setId(int)
method = public int com.ray.pojo.User.getAge()
method = public final void java.lang.Object.wait() throws java.lang.InterruptedException
method = public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
method = public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
method = public boolean java.lang.Object.equals(java.lang.Object)
method = public native int java.lang.Object.hashCode()
method = public final native java.lang.Class java.lang.Object.getClass()
method = public final native void java.lang.Object.notify()
method = public final native void java.lang.Object.notifyAll()
-------- 获得类的方法 - 获得本类的所有方法 ---------
declaredMethod = public java.lang.String com.ray.pojo.User.toString()
declaredMethod = public java.lang.String com.ray.pojo.User.getName()
declaredMethod = public int com.ray.pojo.User.getId()
declaredMethod = public void com.ray.pojo.User.setName(java.lang.String)
declaredMethod = public void com.ray.pojo.User.setAge(int)
declaredMethod = public void com.ray.pojo.User.setId(int)
declaredMethod = public int com.ray.pojo.User.getAge()
declaredMethod = private void com.ray.pojo.User.testPrivate()
-------- 获得类的指定方法 ---------
getName = public java.lang.String com.ray.pojo.User.getName()
method = public void com.ray.pojo.User.setName(java.lang.String)
-------- 获得类的构造器 ---------
constructor = public com.ray.pojo.User()
constructor = public com.ray.pojo.User(java.lang.String,int,int)
declaredConstructor = public com.ray.pojo.User()
declaredConstructor = public com.ray.pojo.User(java.lang.String,int,int)
++ declaredConstructor ++ = public com.ray.pojo.User(java.lang.String,int,int)
Process finished with exit code 0
创建类的对象:调用Class对象的newInstance()方法
思考:难道没有无参的构造器就不能创建对象了吗?只要在操作的时候明确的调用类中的构造器,并将参数传递进入之后,才可实例化操作。
步骤:
通过反射,调用类中的方法,通过Method类完成。
步骤:
package com.ray.demo;
import com.ray.pojo.User;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* @Description: 分析性能问题
* @Author Administrator
* @Date 2020/9/5 15:36
* @Version 1.0
*/
public class Demo10 {
public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
test1();
test2();
test3();
}
// 普通方法调用
public static void test1() {
User user = new User();
long start = System.currentTimeMillis();
for (int i = 0; i < 1000000000; i++) {
user.getName();
}
long end = System.currentTimeMillis();
System.out.println("普通方式执行10亿次: " + (end - start) + "ms");
}
// 反射方式调用
public static void test2() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
User user = new User();
Class c1 = user.getClass();
Method getName = c1.getDeclaredMethod("getName", null);
long start = System.currentTimeMillis();
for (int i = 0; i < 1000000000; i++) {
getName.invoke(user, null);
}
long end = System.currentTimeMillis();
System.out.println("反射方式执行10亿次: " + (end - start) + "ms");
}
// 反射方式调用 -- 关闭检测
public static void test3() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
User user = new User();
Class c1 = user.getClass();
Method getName = c1.getDeclaredMethod("getName", null);
getName.setAccessible(true); // 关闭
long start = System.currentTimeMillis();
for (int i = 0; i < 1000000000; i++) {
getName.invoke(user, null);
}
long end = System.currentTimeMillis();
System.out.println("反射方式(关闭检测)执行10亿次: " + (end - start) + "ms");
}
}
结果
普通方式执行10亿次: 3ms
反射方式执行10亿次: 1283ms
反射方式(关闭检测)执行10亿次: 871ms
完整示例
package com.ray.demo;
import com.ray.pojo.User;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* @Description: 动态的创建对象,通过反射
* @Author Administrator
* @Date 2020/9/5 14:58
* @Version 1.0
*/
public class Demo09 {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
// 获得 Class 对象
Class<?> c1 = Class.forName("com.ray.pojo.User");
// 构造一个对象
User user = (User) c1.newInstance(); // 调用的是无参构造器
System.out.println("user = " + user);
// 通过构造器创建对象
Constructor<?> constructor = c1.getDeclaredConstructor(String.class, int.class, int.class);
User user2 = (User) constructor.newInstance("Ray", 123, 22);
System.out.println("user2 = " + user2);
// 通过反射调用普通方法
User user3 = (User) c1.newInstance();
Method setName = c1.getDeclaredMethod("setName", String.class);
// invoke 激活、调用
// invoke(对象, "方法的值")
setName.invoke(user3, "ray");
System.out.println("user3 = " + user3);
// 通过反射操作属性
User user4 = (User) c1.newInstance();
Field name = c1.getDeclaredField("name");
// can not access a member of class com.ray.pojo.User with modifiers "private"
// private 属性不能直接访问,需要关闭程序的安全检测 setAccessible(true)
name.setAccessible(true);
name.set(user4, "ray2");
System.out.println("user4 = " + user4);
}
}
结果
user = User{name='null', id=0, age=0}
user2 = User{name='Ray', id=123, age=22}
user3 = User{name='ray', id=0, age=0}
user4 = User{name='ray2', id=0, age=0}
类型 | 说明 |
---|---|
ParameterizedType | 表示一种参数化类型,比如Collection<String> |
GenericArrayType | 表示一种元素类型是参数化类型或者类型变量的数组类型 |
TypeVariable | 是各种类型变量的公共父接口 |
WildcardType | 代表一种通配符类型表达式 |
package com.ray.demo;
import com.ray.pojo.User;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;
/**
* @Description: 通过反射获取泛型
* @Author Administrator
* @Date 2020/9/5 15:42
* @Version 1.0
*/
public class Demo11 {
public static void main(String[] args) throws NoSuchMethodException {
Method test01 = Demo11.class.getMethod("test01", Map.class, List.class);
// 获取通用参数类型
Type[] genericParameterTypes = test01.getGenericParameterTypes();
for (Type genericParameterType : genericParameterTypes) {
System.out.println("genericParameterType = " + genericParameterType);
if (genericParameterType instanceof ParameterizedType) {
// 获取参数类型表示的类
Type[] actualTypeArguments = ((ParameterizedType) genericParameterType).getActualTypeArguments();
for (Type actualTypeArgument : actualTypeArguments) {
System.out.println("actualTypeArgument = " + actualTypeArgument);
}
}
}
System.out.println("-----------------------------------------------");
Method test02 = Demo11.class.getMethod("test02", null);
// 获取通用返回类型
Type genericReturnType = test02.getGenericReturnType();
if (genericReturnType instanceof ParameterizedType) {
// 获取返回类型表示的类
Type[] actualTypeArguments = ((ParameterizedType) genericReturnType).getActualTypeArguments();
for (Type actualTypeArgument : actualTypeArguments) {
System.out.println("actualTypeArgument = " + actualTypeArgument);
}
}
}
public void test01(Map<String, User> map, List<User> list) {
System.out.println("test01");
}
public Map<String, User> test02() {
System.out.println("test02");
return null;
}
}
package com.ray.demo;
import com.ray.annotation.Table;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
/**
* @Description: 练习反射操作注解
* @Author Administrator
* @Date 2020/9/5 15:58
* @Version 1.0
*/
public class Demo12 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
// 通过反射获得对象
Class c1 = Class.forName("com.ray.pojo.Teacher");
// 通过反射获得注解
Annotation[] annotations = c1.getAnnotations();
for (Annotation annotation : annotations) {
System.out.println("annotation = " + annotation);
}
// 获取注解的value的值
Table table = (Table) c1.getAnnotation(Table.class);
System.out.println("table.value() = " + table.value());
// 获得类指定的注解
Field name = c1.getDeclaredField("name");
com.ray.annotation.Field annotation = name.getAnnotation(com.ray.annotation.Field.class);
System.out.println("annotation.columnName() = " + annotation.columnName());
System.out.println("annotation.type() = " + annotation.type());
System.out.println("annotation.length() = " + annotation.length());
}
}
结果
annotation = @com.ray.annotation.Table(value=db_teacher)
table.value() = db_teacher
annotation.columnName() = db_name
annotation.type() = varchar
annotation.length() = 10