Java学习路线-30: 反射与类操作

简介: Java学习路线-30: 反射与类操作

第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 类也是单例设计

相关文章
|
1月前
|
存储 Java 索引
用Java语言实现一个自定义的ArrayList类
自定义MyArrayList类模拟Java ArrayList核心功能,支持泛型、动态扩容(1.5倍)、增删改查及越界检查,底层用Object数组实现,适合学习动态数组原理。
86 4
|
1月前
|
IDE JavaScript Java
在Java 11中,如何处理被弃用的类或接口?
在Java 11中,如何处理被弃用的类或接口?
154 5
|
1月前
|
JSON 网络协议 安全
【Java】(10)进程与线程的关系、Tread类;讲解基本线程安全、网络编程内容;JSON序列化与反序列化
几乎所有的操作系统都支持进程的概念,进程是处于运行过程中的程序,并且具有一定的独立功能,进程是系统进行资源分配和调度的一个独立单位一般而言,进程包含如下三个特征。独立性动态性并发性。
141 1
|
1月前
|
Java Go 开发工具
【Java】(8)正则表达式的使用与常用类分享
正则表达式定义了字符串的模式。正则表达式并不仅限于某一种语言,但是在每种语言中有细微的差别。
202 1
|
1月前
|
存储 Java 程序员
【Java】(6)全方面带你了解Java里的日期与时间内容,介绍 Calendar、GregorianCalendar、Date类
java.util 包提供了 Date 类来封装当前的日期和时间。Date 类提供两个构造函数来实例化 Date 对象。第一个构造函数使用当前日期和时间来初始化对象。Date( )第二个构造函数接收一个参数,该参数是从1970年1月1日起的毫秒数。
144 1
|
1月前
|
JSON 网络协议 安全
【Java基础】(1)进程与线程的关系、Tread类;讲解基本线程安全、网络编程内容;JSON序列化与反序列化
几乎所有的操作系统都支持进程的概念,进程是处于运行过程中的程序,并且具有一定的独立功能,进程是系统进行资源分配和调度的一个独立单位一般而言,进程包含如下三个特征。独立性动态性并发性。
158 1
|
1月前
|
编解码 Java 开发者
Java String类的关键方法总结
以上总结了Java `String` 类最常见和重要功能性方法。每种操作都对应着日常编程任务,并且理解每种操作如何影响及处理 `Strings` 对于任何使用 Java 的开发者来说都至关重要。
262 5
|
Java 开发者
奇迹时刻!探索 Java 多线程的奇幻之旅:Thread 类和 Runnable 接口的惊人对决
【8月更文挑战第13天】Java的多线程特性能显著提升程序性能与响应性。本文通过示例代码详细解析了两种核心实现方式:Thread类与Runnable接口。Thread类适用于简单场景,直接定义线程行为;Runnable接口则更适合复杂的项目结构,尤其在需要继承其他类时,能保持代码的清晰与模块化。理解两者差异有助于开发者在实际应用中做出合理选择,构建高效稳定的多线程程序。
181 7
|
Java 开发者
在 Java 中,一个类可以实现多个接口吗?
这是 Java 面向对象编程的一个重要特性,它提供了极大的灵活性和扩展性。
576 58
|
Java 开发者
在Java多线程编程中,创建线程的方法有两种:继承Thread类和实现Runnable接口
【10月更文挑战第20天】在Java多线程编程中,创建线程的方法有两种:继承Thread类和实现Runnable接口。本文揭示了这两种方式的微妙差异和潜在陷阱,帮助你更好地理解和选择适合项目需求的线程创建方式。
240 3
下一篇
oss云网关配置