javaSE-反射
程序员文章站
2022-06-19 08:47:33
关联知识在存在的编程语言中,大致分为动态语言与静态语言这两种。其中静态语言的代表是c,c++等,动态语言的代表则是js,python等。这两种语言的区别有很多,其中最重要的几点如下:静态语言的运行速度要比动态语言更快。动态语言的学习成本低于静态语言。动态语言的开发效率要高于静态语言。…java是介于静态语言与动态语言之间的一门编程语言。它在书写后,需要先进行编译,这是静态语言的特性,编译后生成字节码文件,运行时jvm会将字节码文件加载到内存中,jvm会对字节码文件进行解释执行,这是动态语言的特...
关联知识
在存在的编程语言中,大致分为动态语言与静态语言这两种。其中静态语言的代表是c,c++等,动态语言的代表则是js,python等。这两种语言的区别有很多,其中最重要的几点如下:
- 静态语言的运行速度要比动态语言更快。
- 动态语言的学习成本低于静态语言。
- 动态语言的开发效率要高于静态语言。
- …
java是介于静态语言与动态语言之间的一门编程语言。它在书写后,需要先进行编译,这是静态语言的特性,编译后生成字节码文件,运行时jvm会将字节码文件加载到内存中,jvm会对字节码文件进行解释执行,这是动态语言的特性。其实,在真实的java环境,要比这些更加复杂。
反射简介
java的反射其实就是java程序在运行时动态的操作java代码的一门技术。通过这门技术,我们可以在运行时分析类的信息与结构,也可以在运行时检查对象等。java反射是功能十分强大的一门技术,虽然我们平时开发时并不会经常用到它,但反射却是框架最基层的一门技术。学习好反射,利于后期学习各种框架。
Class类的简介与获取
- Class类是java十分重要的一个类,我们想要使用反射,那就离不开这个类。
- 当jvm加载一个class文件后,就会在内存中生成一个与之相对应的Class对象,这个对象保存着该class文件的全部信息。
- 同一类型的多个实例对象,它们的Class对象都是同一个,即在内存中,每一个Class对象都是独一无二的。
- Class对象的获取方式
- 使用Class类的静态发放forName。如
Class c1 = Class.forName("java.lang.String");
- 使用完整类名.class获取,如
Class c2 = String.class;
- 使用实例对象的getClass()方法获取,如
Class c3 = "sssss".getClass();
- 基本数据类型可是使用类型名.TYPE获取。
示例代码如下:
/**
* @Classname Demo1
* @Date 2020/11/21 12:13
* @author hzq
*/
package com.hzq.reflection;
public class Demo1 {
public static void main(String[] args) throws ClassNotFoundException {
Class c1 = Class.forName("java.lang.String");
Class c2 = String.class;
Class c3 = "sssss".getClass();
Class c4 = "wwwww".getClass();
System.out.println(c1);
System.out.println(c2);
System.out.println(c3);
System.out.println(c4);
System.out.println(c3.equals(c4));
//输出结果
// class java.lang.String
// class java.lang.String
// class java.lang.String
// class java.lang.String
// true
}
}
Class对象的使用
当我们获取了Class对象后,就可以通过调用Class对象的各种发放来对这个java类进行各种操作了。常见的操作有通过Class对象新建一个java类实例对象,操作字段,操作方法,获取各种信息等。
1. 新建对象
通过反射新建对象的方式有两种,方式1是通过Class对象调用newInstance()
方法,该方法要求类必须有公共级别的无参构造器。方式2是通过Class对象调用getConstructor()
方法获取该类的构造器,通过传入不同的参数来获取指定的构造器对象,然后通过构造器对象调用newInstance()
方法来新建对象。
demo如下:
/**
* @Classname Demo2
* @Date 2020/11/21 12:58
* @author hzq
*/
package com.hzq.reflection;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public class Demo2 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
Class<?> c1 = Class.forName("com.hzq.reflection.User");
//方式1
User o1 = (User) c1.newInstance();
//方式2
Constructor<?> constructor = c1.getConstructor();
User o2 = (User) constructor.newInstance(null);
System.out.println(o1);
System.out.println(o2);
//输出结果
// User{name='null', age=null, sex='null'}
// User{name='null', age=null, sex='null'}
}
}
class User{
private String name;
private Integer age;
private String sex;
public User() {
}
public User(String name, Integer age, String sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
", sex='" + sex + '\'' +
'}';
}
}
2. 操作类的字段
demo示例:
/**
* @Classname Demo3
* @Date 2020/11/21 13:14
* @author hzq
*/
package com.hzq.reflection;
import java.lang.reflect.Field;
public class Demo3 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException, InstantiationException {
Class<?> c1 = Class.forName("com.hzq.reflection.User");
System.out.println("获取全部public字段,包括继承来的");
Field[] fields = c1.getFields();
for (Field field : fields) {
System.out.println(field.getName());
}
System.out.println("获取全部字段(不包括继承来的)");
fields = c1.getDeclaredFields();
for (Field field : fields) {
System.out.println(field.getName());
}
System.out.println("获取指定字段");
Field name = c1.getDeclaredField("name");
System.out.println(name.getName());
System.out.println("给通过反射创建的对象设置字段值");
Field age = c1.getDeclaredField("age");
Field sex = c1.getDeclaredField("sex");
User o = (User) c1.newInstance();
//因为字段都为private级别,不可以直接访问,所以我们需要关闭访问检查
name.setAccessible(true);
age.setAccessible(true);
sex.setAccessible(true);
name.set(o,"小明");
sex.set(o,"男");
age.set(o,18);
System.out.println(o);
System.out.println("获取字段name与age的类型");
Class<?> c2 = name.getType();
Class<?> c3 = age.getType();
System.out.println(c2);
System.out.println(c3);
}
//输出结果
// 获取全部public字段,包括继承来的
// 获取全部字段(不包括继承来的)
// name
// age
// sex
// 获取指定字段
// name
// 给通过反射创建的对象设置字段值
// User{name='小明', age=18, sex='男'}
// 获取字段name与age的类型
// class java.lang.String
// class java.lang.Integer
}
3.操作类的方法(包含构造方法)
demo示例:
/**
* @Classname Demo4
* @Date 2020/11/21 15:58
* @author hzq
*/
package com.hzq.reflection;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class Demo4 {
public static void main(String[] args) throws Exception{
Class<?> c1 = Class.forName("com.hzq.reflection.User");
//获取构造方法
Constructor<?> constructor = c1.getConstructor(String.class, Integer.class, String.class);
System.out.println("通过反射获取构造方法来创建对象");
User o = (User) constructor.newInstance("小红", 18, "女");
System.out.println(o);
System.out.println("获取类的全部方法对象,然后全部调用");
Method[] methods = c1.getDeclaredMethods();
//对方法对象的集合进行排序,是的set方法先被调用,然后再调用get方法
List<Method> collect = Arrays.stream(methods).filter(e -> {
if (e.getName().contains("set") || e.getName().contains("get")) {
if (e.getName().contains("getClass")) {
return false;
}
return true;
} else {
return false;
}
}).sorted((x,y)->{
if (x.getName().contains("set")){
return -1;
}else {
return 1;
}
}).collect(Collectors.toList());
//对方法集合进行遍历调用
for (Method method : collect) {
String name = method.getName();
if (name.contains("set")){
if (name.contains("Name")){
method.invoke(o,"小白");
}else if (name.contains("Age")){
method.invoke(o,22);
}else {
method.invoke(o,"男");
}
}else if (name.contains("get")){
Object value = method.invoke(o);
System.out.println(value);
}
}
//输出结果
// 通过反射获取构造方法来创建对象
// User{name='小红', age=18, sex='女'}
// 获取类的全部方法对象,然后全部调用
// 小白
// 22
// 男
}
}
4. 与注解配合使用
demo示例:
/**
* @Classname Demo5
* @Date 2020/11/21 16:27
* @author hzq
*/
package com.hzq.reflection;
import java.lang.annotation.*;
import java.lang.reflect.Field;
public class Demo5 {
public static void main(String[] args) throws Exception{
Class<?> c1 = Class.forName("com.hzq.reflection.Person");
//获取全部类注解
Annotation[] annotations = c1.getDeclaredAnnotations();
for (Annotation annotation : annotations) {
//找出我们自定义的注解
if (annotation instanceof MyAnnotationType){
MyAnnotationType annotationType = (MyAnnotationType) annotation;
//输出注解的属性
System.out.println(annotationType.tableName());
}
}
//获取全部字段
Field[] fields = c1.getDeclaredFields();
for (Field field : fields) {
//获取字段上的注解
MyAnnotationField annotation = field.getAnnotation(MyAnnotationField.class);
//输出注解属性
System.out.println(annotation.fieldName());
}
}
//输出结果
// db_person
// db_name
// db_age
// db_sex
}
/**
* @author admin
* 标注在字段上的注解
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotationField {
String fieldName();
}
/**
* @author admin
* 标注在类上的注解
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotationType {
String tableName();
}
@MyAnnotationType(tableName = "db_person")
class Person{
@MyAnnotationField(fieldName = "db_name")
private String name;
@MyAnnotationField(fieldName = "db_age")
private Integer age;
@MyAnnotationField(fieldName = "db_sex")
private String sex;
public Person() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
}
ps:特别注意
-
getDeclaredxxx
方法获取的是只属于该类的全部方法或字段,getxxx
方法获取的是该类全部公共访问权限的方法或字段,不包含私有的。 - 如果获取的字段或方法对象是私有的,无法直接进行访问,应该先关闭权限检查机制,调用
setAccessible(true)
方法并传入true进行关闭。
本文地址:https://blog.csdn.net/qq_40668912/article/details/109903400