第十二节、轻松学Java_反射

反射与反射类的基本概念

反射指程序可以访问、检测和修改它本身状态或行为的一种能力。
在程序运行过程中, 对于任意一个对象, 都能够知道这个对象所在类的所有属性和方法, 都能够调用它的任意一个方法和访问它的任意一个属性, 这种动态调用对象的方法及动态获取信息的功能称为 Java 语言的反射机制。

Java 提供的反射所需要的类主要有 java.lang.Class 类和 java.lang.reflect 包中的 Field 类、 Constructor 类、Method 类和 Array 类等。
对于任何一个类, 首先要产生一个 Class 的对象, 然后才可以通过 Class 类获得其他的信息。
Field 类封装了反射类的属性。
Constructor 类封装了反射类的构造方法。
Method 类封装反射类的方法。
Array 类提供了动态创建和访问 Java 数组的方法。 它提供的方法都是静态方法。

Class类

获取指定类的Class对象

(1)Object obj = new Object(); //创建 Object 类对象
Class c1 = obj.getClass(); //调用 Object 类的 getClass()方法获取 Class 类对象
(2)Class c2 =Class.forName(“java.lang.Integer”);
(3)Class c3=Integer.Class

package com.test;
import java.lang.reflect.*;
public class ClassTest {
	public static void main(String[] args) {
		try {
			// 获取指定类的Class 对象
			Class c = Class.forName("java.util.Date");
			// 获取类的包信息
			Package p = c.getPackage();
			// 包名
			String pname = p.getName();
			System.out.println("Date 类包信息:" + p);
			System.out.println("Date 类包名:" + pname);
			// 获取类的修饰符
			int m = c.getModifiers();
			String str = Modifier.toString(m);
			System.out.println("Date 类修饰符:" + str);
			System.out.println("Date 类名:" + c.getName());
			// 获取Date 类的字段
			Field[] f = c.getDeclaredFields();
			System.out.println("---循环输出Date 类的字段名---");
			for (Field field : f) {
				System.out.print(field.getName() + " ");
			}
			System.out.println();
			// 获取类的构造方法
			Constructor[] con = c.getDeclaredConstructors();
			System.out.println("---循环输出Date 类的构造方法信息---");
			for (Constructor cc : con) {
				System.out.println(cc.getName() + "的修饰符:" + Modifier.toString(cc.getModifiers()));
				Parameter[] ps = cc.getParameters();
				System.out.println(cc.getName() + "的参数:");
				for (Parameter pp : ps) {
					System.out.print(pp.getName() + " ");
				}
				System.out.println();
			}
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
	}
}

输出:
Date 类包信息:package java.util
Date 类包名:java.util
Date 类修饰符:public
Date 类名:java.util.Date
—循环输出Date 类的字段名—
gcal jcal fastTime cdate defaultCenturyStart serialVersionUID wtb ttb
—循环输出Date 类的构造方法信息—
java.util.Date的修饰符:public
java.util.Date的参数:
arg0 arg1 arg2 arg3 arg4 arg5
java.util.Date的修饰符:public
java.util.Date的参数:
arg0
java.util.Date的修饰符:public
java.util.Date的参数:
java.util.Date的修饰符:public
java.util.Date的参数:
arg0
java.util.Date的修饰符:public
java.util.Date的参数:
arg0 arg1 arg2
java.util.Date的修饰符:public
java.util.Date的参数:
arg0 arg1 arg2 arg3 arg4

生成对象

在 Java 程序中, 通常使用 new 关键字调用类的构造方法来创建对象。 但是, 对于一些特殊情况, 例如程序只有在运行时才知道要创建对象的类名, 就需要使用 Java 的反射机制来创建对象。 使用 Java 的反射机制创建对象有两种方法, 即无参构造方法和有参构造方法。

无参构造方法:
Class c2 = Class.forName(“java.lang.Integer”); //获得 Class 类对象
c2.newInstance(); //使用 Class 类对象的 newInstance()方法生成对象

有参构造方法:
// 第一步,获得指定类的Class 类对象
Class c5 = Class.forName(“java.lang.Integer”);
// 第二步,通过Class 类对象获得指定符合参数类型的构造方法
Constructor construct = c5.getConstructor(int.class);
// 第三步,通过Constructor 类对象的newInstance()方法传入参数,创建对象
Integer in = (Integer) construct.newInstance(1246);

Method类

class Computer// 计算机类
{
	private double frequency = 2.0;
	private int RAM = 4;
	private int HardDisk = 500;
	private String CPU = "Intel";

	public Computer()// 无参构造方法
	{
	}

	public Computer(double frequency, int RAM, int HardDisk, String CPU)// 有参构造方法
	{
		this.frequency = frequency;
		this.RAM = RAM;
		this.HardDisk = HardDisk;
		this.CPU = CPU;
	}

	// 为了能实现复制,下面的方法需按Bean 规则写,即setter 或getter
	public void setFrequency(double frequency) {
		this.frequency = frequency;
	}

	public double getFrequency() {
		return frequency;
	}

	public void setRAM(int RAM) {
		this.RAM = RAM;
	}

	public int getRAM() {
		return RAM;
	}

	public void setHardDisk(int HardDisk) {
		this.HardDisk = HardDisk;
	}

	public int getHardDisk() {
		return HardDisk;
	}

	public void setCPU(String CPU) {
		this.CPU = CPU;
	}

	public String getCPU() {
		return CPU;
	}

	public String toString() {
		String info = "主频:" + frequency + "MHz 内存:" + RAM + "GB 硬盘:" + HardDisk + "GB CPU:" + CPU;
		return info;
	}
}

public class Test {
	public static void main(String args[]) throws Exception {
		// 获得一个表示Computer 类的Class 类对象
		Class obj = Class.forName("haha.test.Computer");
		// 获取Computer 类中的构造方法
		Constructor constructor[] = obj.getConstructors();
		System.out.println("Computer 类中的构造方法:");
		for (Constructor con : constructor)// 将构造方法输出
			System.out.println(con.toString());
		System.out.println();
		// 获取Computer 类中的所有域
		Field field[] = obj.getDeclaredFields();
		System.out.println("Computer 类中的域:");
		for (Field f : field)
			System.out.println(f.toString());
		System.out.println();
		// 获取Computer 类中的所有方法
		Method method[] = obj.getDeclaredMethods();
		System.out.println("Computer 类中的方法:");
		for (Method m : method)
			System.out.println(m);
		System.out.println();
		Computer myComputer = new Computer(2.4, 4, 450, "Intel");// 声明一个对象
		Computer aComputer = (Computer) duplicate(myComputer);// 复制一个对象
		System.out.println("复制后的对象:");
		System.out.println(aComputer.toString());// 输出复制后的对象
	}

	private static Object duplicate(Object source) throws Exception {
		// 由对象source 获得对应的Class 类对象
		Class classObj = source.getClass();
		// 获得source 类对象所在类中的所有域
		Field[] sourceFields = classObj.getDeclaredFields();
		// 利用classObj 调用方法newInstance()获得一个新对象
		Object target = classObj.newInstance();
		// 将source 对象的域值赋给新对象对应的域
		for (Field sourceField : sourceFields) {
			sourceField.setAccessible(true);// 设置域可访问
			// 赋值给新对象对应的域值
			sourceField.set(target, sourceField.get(source));
		}
		return target;
	}
}
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

身影王座

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值