Java学习路线-30: 反射与类操作
  TEZNKK3IfmPf 2023年11月12日 58 0

第23 章 : 反射与类操作

104 反射获取类结构信息

反射机制处理不仅仅只是一个实例化对象的处理,

更多情况下还有类的组成结构操作

任何一个类的组成结构:

父类、父接口、包、属性、方法(构造方法,普通方法)

// 获取包名 
public Package getPackage()

// 获取继承父类
public native Class<? super T> getSuperclass()

// 获取实现父接口
public Class<?>[] getInterfaces()
import java.util.Arrays;

abstract class AbstractHuman{
}

interface IConnectService{
public boolean isConnect();
}

interface IChannelService{
public void send();
}

class Person extends AbstractHuman implements IConnectService, IChannelService{

@Override
public boolean isConnect() {
return true;
}

@Override
public void send() {
if(this.isConnect()){
System.out.println("发送");
}
}
}

class Demo{
public static void main(String[] args) {
Class<?> cls = Person.class;

System.out.println(cls.getPackage());
// null

System.out.println(cls.getSuperclass());
// class AbstractHuman

System.out.println(Arrays.toString(cls.getInterfaces()));
// [interface IConnectService, interface IChannelService]
}
}

105 反射调用构造方法

实例化方法

// 获取指定构造方法
public Constructor<T> getConstructor(Class<?>... parameterTypes)
public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)

// 获取全部构造方法
public Constructor<?>[] getConstructors()
public Constructor<?>[] getDeclaredConstructors()


Class.getDeclaredConstructor().newInstance()
class Person{
private String name;
private int age;

public Person(String name, int age) {
this.name = name;
this.age = age;
}

@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}

class Demo{
public static void main(String[] args) throws Exception {
Class<?> cls = Person.class;

// 获取有参构造
Constructor constructor = cls.getConstructor(String.class, int.class);
Object obj = constructor.newInstance("小强", 23);
System.out.println(obj);
// Person{name='小强', age=23}
}
}

使用反射的类最好提供无参构造方法,便于统一操作

继承关系

AccessibleObject(AnnotatedElement)
-Executable
-Constructor
-Method
-Field(Member)

106 反射调用普通方法

了解即可

// 获取指定方法
public Method getMethod(String name, Class<?>... parameterTypes)

// 获取全部方法
public Method[] getMethods()

// 获取本类方法
public Method getDeclaredMethod(String name, Class<?>... parameterTypes)

// 获取本类全部方法
public Method[] getDeclaredMethods()
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Arrays;

class Person {
public String geMessage(String message) {
return message;
}
}

class Demo {
public static void main(String[] args) throws Exception {
Class<?> cls = Person.class;
Method method = cls.getMethod("geMessage", String.class);

System.out.println(method);
// public java.lang.String Person.geMessage(java.lang.String)

System.out.println(Modifier.toString(method.getModifiers()));
// public

System.out.println(method.getReturnType().getName());
// java.lang.String

System.out.println(method.getName());
// geMessage

System.out.println(Arrays.toString(method.getParameterTypes()));
// [class java.lang.String]
}
}

Method类 重要方法 invoke

// 反射调用类中的方法
public Object invoke(Object obj, Object... args)

整个操作形式上没有任何明确的类对象产生,依靠反射操作,避免耦合问题

import java.lang.reflect.Method;

class Person {
private String name;

public Person() {
}

public Person(String name) {
this.name = name;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}
}

class Demo {
public static void main(String[] args) throws Exception {
Class<?> cls = Class.forName("Person");
String key = "name";
String value = "Tom";

// 获取指定方法
Method setNameMethod = cls.getMethod("setName", String.class);
Method getNameMethod = cls.getMethod("getName");

// 调用无参构造方法实例化
Object obj = cls.getDeclaredConstructor().newInstance();

setNameMethod.invoke(obj, value); // 等价于 person.setName(value)
System.out.println(getNameMethod.invoke(obj));
// Tom

}
}

107 反射调用成员

// 获取本类全部成员
public Field[] getDeclaredFields()

// 获取本类指定成员
public Field getDeclaredField(String name)

// 获取父类全部成员
public Field[] getFields()

// 获取父类指定成员
public Field getField(String name)

Field 类

// 设置属性内容
public void set(Object obj, Object value)

// 获取属性内容
public Object get(Object obj)

// 解除封装
public void setAccessible(boolean flag)
import java.lang.reflect.Field;

class Person {
private String name;

public Person() {

}
}

class Demo {
public static void main(String[] args) throws Exception {
Class<?> cls = Class.forName("Person");
Object obj = cls.getDeclaredConstructor().newInstance();

Field nameField = cls.getDeclaredField("name");

// 解除封装性,访问私有成员
nameField.setAccessible(true);

nameField.set(obj, "Tom");
System.out.println(nameField.get(obj));
// Tom
}
}

不建议打破封装机制

Field类重要方法 getType

public Class<?> getType()
Class<?> cls = Class.forName("Person");

Field nameField = cls.getDeclaredField("name");

System.out.println(nameField.getType());
// class java.lang.String

System.out.println(nameField.getType().getName());
// 获取包.类 java.lang.String

System.out.println(nameField.getType().getSimpleName());
// 获取类名称 String

108 Unsafe工具类

通过反射获取对象,并且直接使用底层的C++代码

可以绕过JVM相关管理机制,就无法使用内存管理和垃圾回收

Unsafe 类

public final class Unsafe {
private static final Unsafe theUnsafe;
private Unsafe() {}
}

Unsafe绕过实例化对象的管理

import sun.misc.Unsafe;

import java.lang.reflect.Field;

// 将构造函数私有化
class Person{
private Person(){};
public void print(){
System.out.println("hi");
}
}

class Demo {
public static void main(String[] args) throws Exception {

Field theUnsafeField = Unsafe.class.getDeclaredField("theUnsafe");
theUnsafeField.setAccessible(true);
Unsafe unsafeObject = (Unsafe) theUnsafeField.get(null);

// 通过unsafe 实例化构造函数私有化的对象
Person person = (Person) unsafeObject.allocateInstance(Person.class);
person.print();
// hi

}
}

如果不是必须的情况下,不建议使用

Unsafe 类也是单例设计

【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年11月12日 0

暂无评论

推荐阅读
  TEZNKK3IfmPf   19天前   43   0   0 java
  TEZNKK3IfmPf   2024年05月31日   54   0   0 java
TEZNKK3IfmPf