Java反射-类基本操作


Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为Java语言的反射机制。实际上,我们创建的每一个类也都是对象,即类本身是java.lang.Class类的实例对象。这个实例对象称之为类对象,也就是Class对象。那么,Class对象又是什么对象呢?

一、Class对象

1.1 类描述

Class对象特点

1.2 类方法

类方法

1.3 特点

  • Class类的实例对象表示正在运行的Java应用程序中的类和接口。也就是JVM中有很多类的实例对象,每个类都有唯一的Class对象。
  • Class类没有公共构造方法Class对象是加载类时由Java虚拟机自动构造的。也就是说由JVM类加载器自动创建。
  • Class对象用于提供类本身的信息,比如有几种构造方法, 有多少属性,有哪些普通方法。

二、类对象

2.1 获取类对象

  • Class.forName("package.T")(常用)
  • T.class
  • new T().getClass()

在一个JVM中,一种类只会有一个类对象存在。所以,以上三种方式获取的都是都是同一个类对象。准确地说,是在ClassLoader下只有一个类对象。
示例

public static void main(String[] args) {
	String className = "package.T";
	try {
		Class forNameClass = Class.forName(className);
		Class directClass = T.class;
		Class objectClass = new T().getClass();
		
		System.out.println(forNameClass == directClass); // print true
		System.out.println(forNameClass == objectClass); // print true
	} catch (ClassNotFoundException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}
}

2.2 获取类构造器

获取类构造方法

  1. 批量方法
    public Constructor[] getConstructors():获取所有"公有的"构造器方法
    public Constructor[] getDeclaredConstructors():获取所有构造方法(包括私有、受保护、默认、公有)

  2. 获取单个方法
    public Constructor getConstructor(Class... parameterTypes):获取单个"公有的"构造器方法
    public Constructor getDeclaredConstructor(Class... parameterTypes):获取单个"公有的"构造器方法(包括私有的、受保护、默认或公有的)

示例

package pojo;

public class User {
    /** 姓名 */
    public String userName;
    /** 年龄 */
    private Integer age;
    /** 住所 */
    private String address;

    /** 无参构造器 **/
    public User() {

    }

    /** public修饰符, 带参构造器 **/
    public User(String userName, Integer age) {
        this(userName, age, null);
    }

    /** private修饰符, 带参构造器 **/
    private User(String userName, Integer age, String address) {
        this.userName = userName;
        this.age = age;
        this.address = address;
    }
    
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException {
        //1. 加载Class对象
        Class<?> forNameClass = Class.forName("pojo.User");

        //2. 获取所有公有构造方法
        System.out.println("**********************所有公有构造方法*********************************");
        Constructor<?>[] constructors = forNameClass.getConstructors();
        //  打印信息
        //  public pojo.User(java.lang.String,java.lang.Integer)
        //  public pojo.User()
        Stream.of(constructors).forEach(e -> System.out.printf("  %s\n", e.toString()));

        System.out.println("************所有的构造方法(包括:私有、受保护、默认、公有)***************");
        //  打印信息
        //  private pojo.User(java.lang.String,java.lang.Integer,java.lang.String)
        //  public pojo.User(java.lang.String,java.lang.Integer)
        //  public pojo.User()
        Constructor<?>[] declaredConstructors = forNameClass.getDeclaredConstructors();
        Stream.of(declaredConstructors).forEach(e -> System.out.printf("  %s\n", e.toString()));

        System.out.println("*****************获取公有、无参的构造方法*******************************");
        // 打印信息
        // public pojo.User()
        Constructor<?> publicNoArgConstructor = forNameClass.getConstructor();
        System.out.printf("  %s\n", publicNoArgConstructor.toString());

        System.out.println("******************获取公有构造方法*******************************");
        // 打印信息
        // public pojo.User(java.lang.String,java.lang.Integer)
        Constructor<?> publicArgConstructor = forNameClass.getDeclaredConstructor(String.class, Integer.class);
        System.out.printf("  %s\n", publicArgConstructor.toString());

        System.out.println("******************获取私有构造方法*******************************");
        // 打印信息
        //private pojo.User(java.lang.String,java.lang.Integer,java.lang.String)
        Constructor<?> privateArgConstructor = forNameClass.getDeclaredConstructor(String.class, Integer.class, String.class);
        System.out.printf("  %s\n", privateArgConstructor.toString());
    }
}

2.3 创建类对象

调用Constructor对象的newInstance(Object... initArgs)创建类对象实例。
示例

public static void main(String[] args)
        throws ClassNotFoundException, NoSuchMethodException,
        IllegalAccessException, InvocationTargetException, InstantiationException {
    Class<?> forNameClass = Class.forName("pojo.User");

    System.out.println("*****************获取公有、无参的构造方法*******************************");
    // 打印信息
    // User(userName=null, age=null, address=null)
    Constructor<?> publicNoArgConstructor = forNameClass.getConstructor();
    Object publicNoArgObject = publicNoArgConstructor.newInstance();
    System.out.println(publicNoArgObject);

    System.out.println("******************获取公有构造方法*******************************");
    // 打印信息
    // User(userName=ioteye, age=18, address=null)
    Constructor<?> publicArgConstructor = forNameClass.getDeclaredConstructor(String.class, Integer.class);
    Object publicArgObject = publicArgConstructor.newInstance("ioteye", 18);
    System.out.println(publicArgObject);

    System.out.println("******************获取私有构造方法*******************************");
    // 打印信息
    // User(userName=ioteye, age=18, address=sz)
    Constructor<?> privateArgConstructor = forNameClass.getDeclaredConstructor(String.class, Integer.class, String.class);
    // 设置对象访问标志设置为公有
    privateArgConstructor.setAccessible(true);
    Object privateArgObject = privateArgConstructor.newInstance("ioteye", 18, "sz");
    System.out.println(privateArgObject);
}

三、类成员变量

3.1 获取成员变量

获取方式

  1. 批量方法
    clazz.getFields():获取所有公有的成员变量(包括从父类继承的成员变量)
    clazz.getDeclaredFields():获取所有成员变量(包括私有、默认、受保护或公有,不包括从父类继承的成员变量)
  2. 获取单个方法
    clazz.getField(String name):获取单个公有的成员变量(包括从父类继承的成员变量)
    clazz.getDeclaredField(String name):获取单个成员变量(包括私有、默认、受保护或公有,不包括从父类继承的成员变量)

示例

package pojo;

import java.lang.reflect.Field;
import java.util.stream.Stream;

public class User {
	/** 静态ID **/
    private static final String ENV = "TEST";
    /** 姓名 */
    public String userName;
    /** 年龄 */
    private Integer age;
    /** 住所 */
    private String address;

    public static void main(String[] args)
            throws ClassNotFoundException, NoSuchFieldException {
        Class<?> forNameClass = Class.forName("pojo.User");

        System.out.println("*****获取所有公有的成员变量(包括从父类继承的成员变量)******");
        // 打印信息
        // public java.lang.String pojo.User.userName
        Field[] fields = forNameClass.getFields();
        Stream.of(fields).forEach(System.out::println);

        System.out.println("******获取所有成员变量(包括私有、默认、受保护或公有,不包括从父类继承的成员变量)******");
        // 打印信息
        // public java.lang.String pojo.User.userName
        // private java.lang.Integer pojo.User.age
        // private java.lang.String pojo.User.address
        Field[] declaredFields = forNameClass.getDeclaredFields();
        Stream.of(declaredFields).forEach(System.out::println);

        System.out.println("******************获取单个公有的成员变量*******************************");
        // 打印信息
        // public java.lang.String pojo.User.userName
        Field userNameField = forNameClass.getField("userName");
        System.out.println(userNameField);

        System.out.println("******************获取单个私有成员变量*******************************");
        // 打印信息
        // private java.lang.Integer pojo.User.age
        Field ageField = forNameClass.getDeclaredField("age");
        System.out.println(ageField);
    }
}

3.2 Field类介绍

Field类介绍

3.3 Field类方法摘要

Field类方法摘要

3.4 成员变量赋值

public class User {
    /** 静态ID **/
    private static final String ENV = "TEST";

    /** 姓名 */
    public String userName;
    /** 年龄 */
    private Integer age;
    /** 住所 */
    private String address;
    
	public static void main(String[] args)
	        throws ClassNotFoundException, NoSuchMethodException,
	        InstantiationException, IllegalAccessException, InvocationTargetException,
	        NoSuchFieldException {
	    Class<?> forNameClass = Class.forName("pojo.User");
	
	    System.out.println("******获取公有、无参的构造方法******");
	    Constructor<?> constructor = forNameClass.getConstructor();
	    Object instance = constructor.newInstance();
	
	    System.out.println("******************获取单个公有的成员变量*******************************");
	    Field userNameField = forNameClass.getField("userName");
	    userNameField.set(instance, "ioteye");
	
	    System.out.println("******************获取单个私有成员变量*******************************");
	    Field ageField = forNameClass.getDeclaredField("age");
	    ageField.setAccessible(true);
	    ageField.set(instance, 18);
	
	    // 打印信息
	    // User(userName=ioteye, age=18, address=null)
	    System.out.println(instance);
	
	    System.out.println("******************获取静态字段*******************************");
	    // 打印信息
	    // TEST
	    Field envField = forNameClass.getDeclaredField("ENV");
	    envField.setAccessible(true);
	    Object value = envField.get(instance);
	    System.out.println(value);
	}
}

四、类方法

4.1 获取方法

获取方式

  1. 批量方法
    clazz.getMethods():获取所有公有的方法(包括父类继承的)
    clazz.getDeclaredMethods():获取所有方法(包括私有、默认、受保护和公有的,以及类方法,但是不包括父类继承的方法)
  2. 获取单个方法
    clazz.getField(String name):获取单个公有的方法(包括父类继承的)
    clazz.getDeclaredField(String name):获取单个方法(包括私有、默认、受保护和公有的,以及类方法,但是不包括父类继承的方法)

注意获取的方法中不包括构造器方法

示例

package pojo;

import java.lang.reflect.Method;
import java.util.stream.Stream;

public class User {
    /** 静态ID **/
    private static final String ENV = "TEST";

    /** 姓名 */
    public String userName;
    /** 年龄 */
    private Integer age;
    /** 住所 */
    private String address;

    /** 无参构造器 **/
    public User() {

    }

    /** private修饰符, 带参构造器 **/
    private User(String userName, Integer age) {
        this(userName, age, null);
    }

    /** private修饰符, 带参构造器 **/
    private User(String userName, Integer age, String address) {
        this.userName = userName;
        this.age = age;
        this.address = address;
    }

    /** public修饰符, 无参方法 */
    public void printInfo() {
        System.out.printf("%s is %d years old, and his hometown is %s\n", userName, age, address);
    }

    /** private修饰符, 无参方法 */
    private void gotoAddress(String gotoAddress) {
        System.out.printf("%s is %d years old, went to work in %s\n", userName, age, gotoAddress);
    }

    /** private和static修饰符, 带参方法 */
    private static User newInstance(String userName, Integer age, String address) {
        return new User(userName, age, address);
    }

    public static void main(String[] args)
            throws ClassNotFoundException, NoSuchMethodException{
        Class<?> forNameClass = Class.forName("pojo.User");

        System.out.println("****获取所有公有的方法(包括父类继承的)****");
        // 打印信息
        // public static void pojo.User.main(java.lang.String[]) 
        //              throws java.lang.ClassNotFoundException,java.lang.NoSuchMethodException
        // public void pojo.User.printInfo()
        // public final void java.lang.Object.wait() throws java.lang.InterruptedException
        // public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
        // public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
        // public boolean java.lang.Object.equals(java.lang.Object)
        // public java.lang.String java.lang.Object.toString()
        // public native int java.lang.Object.hashCode()
        // public final native java.lang.Class java.lang.Object.getClass()
        // public final native void java.lang.Object.notify()
        // public final native void java.lang.Object.notifyAll()
        Method[] methods = forNameClass.getMethods();
        Stream.of(methods).forEach(System.out::println);

        System.out.println("****获取所有方法(包括私有、默认、受保护和公有的,以及类方法,但是不包括父类继承的方法)****");
        // 打印信息
        // public static void pojo.User.main(java.lang.String[])
        //                 throws java.lang.ClassNotFoundException,java.lang.NoSuchMethodException
        // private static pojo.User pojo.User.newInstance(java.lang.String,java.lang.Integer,java.lang.String)
        // public void pojo.User.printInfo()
        // private void pojo.User.gotoAddress(java.lang.String)
        Method[] declaredMethods = forNameClass.getDeclaredMethods();
        Stream.of(declaredMethods).forEach(System.out::println);

        System.out.println("**********获取单个公有、无参方法**********");
        // 打印信息
        // public void pojo.User.printInfo()
        Method printInfoMethod = forNameClass.getMethod("printInfo");
        Stream.of(printInfoMethod).forEach(System.out::println);

        System.out.println("****获取单个私有、带参方法****");
        // 打印信息
        // private void pojo.User.gotoAddress(java.lang.String)
        Method gotoAddressMethod = forNameClass.getDeclaredMethod("gotoAddress", String.class);
        Stream.of(gotoAddressMethod).forEach(System.out::println);

        System.out.println("****获取单个有返回值、私有类方法****");
        // 打印信息
        // private static pojo.User pojo.User.newInstance(java.lang.String,java.lang.Integer,java.lang.String)
        Method newInstanceMethod = forNameClass.getDeclaredMethod("newInstance", String.class, Integer.class, String.class);
        Stream.of(newInstanceMethod).forEach(System.out::println);
    }
}

4.2 Method类介绍

Method类介绍

4.2 Method类方法摘要

Method类方法摘要

4.4 方法反射调用

package pojo;

import lombok.Data;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

@Data
public class User {
    /** 静态ID **/
    private static final String ENV = "TEST";

    /** 姓名 */
    public String userName;
    /** 年龄 */
    private Integer age;
    /** 住所 */
    private String address;

    /** private修饰符, 带参构造器 **/
    private User(String userName, Integer age, String address) {
        this.userName = userName;
        this.age = age;
        this.address = address;
    }

    /** public修饰符, 无参方法 */
    public void printInfo() {
        System.out.printf("%s is %d years old, and his hometown is %s\n", userName, age, address);
    }

    /** private修饰符, 无参方法 */
    private void gotoAddress(String gotoAddress) {
        System.out.printf("%s is %d years old, went to work in %s\n", userName, age, gotoAddress);
    }
    
    /** private和static修饰符, 带参方法 */
    private static User newInstance(String userName, Integer age, String address) {
        return new User(userName, age, address);
    }

    public static void main(String[] args)
            throws ClassNotFoundException, NoSuchMethodException,
            InstantiationException, IllegalAccessException, InvocationTargetException {
        Class<?> forNameClass = Class.forName("pojo.User");

        System.out.println("******获取公有、无参构造方法******");
        Constructor<?> constructor = forNameClass.getDeclaredConstructor(String.class, Integer.class, String.class);
        constructor.setAccessible(true);
        Object instance = constructor.newInstance("ioteye", 18, "sz");

        System.out.println("****获取单个公有、无参方法****");
        // 打印信息
        // ioteye is 18 years old, and his hometown is sz
        Method printInfoMethod = forNameClass.getMethod("printInfo");
        printInfoMethod.invoke(instance);

        System.out.println("****获取单个私有、带参方法****");
        // 打印信息
        // ioteye is 18 years old, went to work in bj
        Method gotoAddressMethod = forNameClass.getDeclaredMethod("gotoAddress", String.class);
        gotoAddressMethod.setAccessible(true);
        gotoAddressMethod.invoke(instance,"bj");

        System.out.println("****获取单个有返回值、私有类方法****");
        // 打印信息
        // User(userName=ioteye-1, age=18, address=sz)
        Method newInstanceMethod = forNameClass.getDeclaredMethod("newInstance", String.class, Integer.class, String.class);
        newInstanceMethod.setAccessible(true);
        Object invokeResult = newInstanceMethod.invoke(null, "ioteye-1", 18, "sz");
        System.out.println(invokeResult);
    }
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值