这是我参与11月更文挑战的第20天,活动详情查看:2021最后一次更文挑战
2.2 反射机制
-
Java反射机制提供的功能
- 在运行时判断任意一个对象所属的类
- 在运行时构造任意一个类的对象
- 在运行时判断任意一个类所具有的成员变量和成员方法
- 在运行时获取泛型信息
- 在运行时调用任意一个对象的成员变量和成员方法
- 在运行时处理注解
- 生成动态代理
- ......
-
反射机制的优缺点:
- 优点:可以实现动态创建对象和编译,体现出相当大的灵活性
- 缺点:对性能有影响。使用反射基本上是一种解释操作,我们可以告诉JVM,我们希望它做什么并且它能够满足我们的要求。这类操作总是慢于直接执行相同的操作(基于这个原因,在没有什么特殊情况时,不得使用反射)
-
反射的API:
- java.lang.Class : 代表一个类
- java.lang.reflect.Method : 代表类的方法
- java.lang.reflect Field : 代表类的成员变量
- java.lang.reflect.Constructure : 代表类的构造器
- ......
package refection ;
import java.util.Objects;
// 反射
public class Test {
@SuppressWarnings("all")
public static void main(String[] args) throws ClassNotFoundException {
// 创建对象,实际上时需要泛型的,但是没有,用不到,直接去掉。 看着难受就强行镇压黄色的提示
Class c1 = Class.forName("refection.User");
// 一个类在内存中只有一个Class对象,可以进行验证
// 验证的方式:多次获取,看哈希码是否相同
// 一个类被加载之后,类的整个结构都会被封装在Class对象中
Class c2 = Class.forName("refection.User");
Class c3 = Class.forName("refection.User");
Class c4 = Class.forName("refection.User");
System.out.println(c2.hashCode());
System.out.println(c3.hashCode());
System.out.println(c4.hashCode());
}
}
// 实体类:pojo、entity类
class User{
private String name ;
private int id ;
private int age ;
public User() {
}
public User(String name, int id, int age) {
this.name = name;
this.id = id;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "User{" +
"name='" + name + ''' +
", id=" + id +
", age=" + age +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
User user = (User) o;
return id == user.id &&
age == user.age &&
Objects.equals(name, user.name);
}
@Override
public int hashCode() {
return Objects.hash(name, id, age);
}
}
2.3 获得class对象的几种方式
-
获取class对象的方式一共有三种:
- 方式一:通过对象获得
- 方式二:通过反射forName获得
- 方式三:通过类名.class获得
- 方式四:通过内置的基本数据类型的包装类
- 方式五:通过ClassLoader(后面讲解)
package refection ;
import java.util.Objects;
public class Test02 {
@SuppressWarnings("all")
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());
// - 方式二:通过反射forName获得
Class c2 = Class.forName("refection.Student");
System.out.println(c2.hashCode());
// - 方式三:通过类名.class获得
Class c3 = Student.class ;
System.out.println(c3.hashCode());
// 方式四:通过内置类型的包装类都有一个Type属性
Class c4 = Integer.TYPE ;
System.out.println(c4);
System.out.println(c4.hashCode());
// 获取父类型
Class c5 = c1.getSuperclass();
System.out.println(c5);
}
}
class Person {
public String name ;
public Person (){
}
public Person(String name){
this.name = name ;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + ''' +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person person = (Person) o;
return Objects.equals(name, person.name);
}
@Override
public int hashCode() {
return Objects.hash(name);
}
}
class Student extends Person{
public Student(){
this.name = "学生" ;
}
}
class Teacher extends Person{
public Teacher(){
this.name = "教师" ;
}
}