java小白——关于java中的反射

反射概念

  • 反射指程序可以访问、检测和修改它本身状态或行为的一种能力。反射使程序的代码能够得到装载到Java 虚拟机中的类的内部信息。本章将详细介绍 Java 的反射机制,主要内容包括 java.lang.reflect 包提供的Class 类、 Constructor 类、 Method 类、 Field 类和 Array 类等,以及ParameterizedType 接口如何获取泛型类、泛型方法的信息。*

    通过 Java 的反射机制, 程序员可以方便、 灵活地创建代码, 这些代码可以在运行时进行装配, 在程序运行过程中可以动态地扩展程序。
    Java 的反射机制主要有以下功能:

  1. 在运行时判断任意一个对象所属的类。
  2. 在运行时构造任意一个类的对象。
  3. 在运行时判断任意一个类所具有的成员变量和方法。
  4. 在运行时调用任意一个对象的方法。
  5. 生成动态代理。

反射类

Java 提供的反射所需要的类主要有 java.lang.Class 类和 java.lang.reflect 包中的 Field 类、 Constructor 类、Method 类和 Array 类等。

  1. Class 类的实例表示正在运行的 Java 应用程序中的类和接口。 它是 Java 反射的基础, 对于任何一个类, 首先要产生一个 Class 的对象, 然后才可以通过 Class 类获得其他的信息。
  2. Field 类提供有关类或接口的单个字段的信息以及对它的动态访问权限。 反射的字段可能是一个类( 静态) 字段或实例字段。 该类封装了反射类的属性。
  3. Constructor 类提供关于类的单个构造方法的信息以及对它的访问权限。 该类封装了反射类的构造方法。
  4. Method 类提供关于类或接口上单独某个方法的信息, 该方法可能是类方法或实例方法( 包括抽象方法)。 该类是用来封装反射类的方法。
  5. Array 类提供了动态创建和访问 Java 数组的方法。 它提供的方法都是静态方法。

1. 测试代码一获取反射类的对象(三种方式):

package test;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.lang.reflect.Constructor;
import java.lang.reflect.Parameter;
public class Classtest1 {

	public static void main(String[] args) throws ClassNotFoundException {
		Object obj = new Object();
		Class c1 = obj.getClass();
		try{
			Class c2 = Class.forName("java.util.Date");//获取Class对象的三种方法
        Class c3 = Integer.class;
        System.out.println(c2);
        Package p = c2.getPackage();
        System.out.println("Date类包名信息"+p);
        int m = c2.getModifiers();//获取类的修饰符
        String str = Modifier.toString(m);//强制类型转换修饰符
        System.out.println("Date的类修饰符"+str);
        System.out.println("Date的类名"+c2.getName());
        Field[]f = c2.getDeclaredFields();//获取Date类的字段
        System.out.println("foreach循环输出Date类的字段名");
        for(Field field : f){
        	System.out.print(field.getName()+"  ");
        }
        System.out.println();
        Constructor[]con = c2.getConstructors();//获取Date的构造方法
        System.out.println("循环输出Date类的构造方法信息");
        for(Constructor cc : con){
        	System.out.print(cc.getName()+"的修饰符:"+Modifier.toString(cc.getModifiers()));
        	System.out.println();
        	Parameter[] ps = cc.getParameters();//获取构造方法中的参数
            System.out.println(cc.getName()+"的参数");
            for(Parameter pp : ps){//嵌套的foreach循环
            	System.out.print(pp.getName()+"  ");
            }
            System.out.println();
        }
		}catch(ClassNotFoundException e){
			e.printStackTrace();
		}
	}

}

运行结果:
class java.util.Date
Date类包名信息package java.util, Java Platform API Specification, version 1.8
Date的类修饰符public
Date的类名java.util.Date
foreach循环输出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

2. 测试代码二有参和无参的构造方法:

package test;

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

public class Classtest2 {

	public static void main(String[] args) {
		try {
			Class c1 = Class.forName("java.util.Date");
			c1.newInstance();//在程序运行中才新建类的对象并且要捕捉空值的异常(无参数构造方法)
			System.out.println(c1.newInstance());
			
			
			
			Class c2 = Class.forName("java.lang.Integer");
			//第一步,通过Class类对象c2
			Constructor construct = c2.getConstructor(int.class);
			//第二步,通过Class类对象c2的方法getConstruct()方法获得指定符合参数类型的构造方法
			Integer in = (Integer)construct.newInstance(2341324);
			//第三步,通过Constructor类对象construct的newInstrance()方法传入参数,创建对象(有参构造方法)
			System.out.println(in);
		} catch (Exception e) {//
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

}

运行结果:
Wed Nov 20 21:03:13 CST 2019
2341324

3. 测试代码三
java.lang.reflect包中Construct类,Method类,Field类的方法

package test;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.lang.reflect.Field;

public class ReflectTest1 {

	public static void main(String[] args) {
		try {
			Class obj = Class.forName("test.Computer");//获取一个表示Computer的Class类的对象
			Constructor constructor[] = obj.getConstructors();//获取Computer类中的构造方法
			System.out.println("Computer类中的构造方法:");
			for(Constructor con : constructor)//将构造方法输出
			        System.out.println(con.toString());
			System.out.println();
			Field field[] = obj.getDeclaredFields();//获取Computer中的所有域
			System.out.println("Computer类中的域:");
			for(Field f : field)
					System.out.println(f.toString());
			System.out.println();
			Method method[] = obj.getMethods();//获取Computer类中的所有方法
			System.out.println("Computer类中的方法:");
			for(Method m : method)
				   System.out.println(m.toString());
			System.out.println();
			Computer myComputer = new Computer(2.5,4,450,"Inter");//声明一个对象
			Computer aComputer = (Computer) duplicate(myComputer);// 复制一个对象
			System.out.println("复制后的对象:");
			System.out.println(aComputer.toString());//输出复制后的对象
			
		} catch (Exception e) {//用try—catch抛出反射信息中的所有异常
			e.printStackTrace();
		}
	}

	private static Object duplicate(Object source) throws Exception {
		Class classObj = source.getClass();//由对象source获得对应的Class对象
		
		Field [] sourceFields = classObj.getDeclaredFields();//获得source类对象所在类中的所有域
		
		Object target = classObj.newInstance();//利用classObj.newInstrance()方法获得一个新对象
		
		for(Field sourceField : sourceFields){//将source对象的域值赋给新对象对应的域
			sourceField.setAccessible(true);//设置域可访问true
			sourceField.set(target, sourceField.get(source));
		}
		return target;
	}


}
class Computer{//电脑类
	private double frequency = 2.0;
	private int RAM = 4;
	private int HardDisk = 500;
	private String CPU = "Inter";
	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 ss = "主频:" + frequency + "MHz 内存:" + RAM + "GB 硬盘:" + HardDisk + "GB CPU:" + CPU;
		return ss;
	}
}

运行结果:
Computer类中的构造方法:
public test.Computer()
public test.Computer(double,int,int,java.lang.String)

Computer类中的域:
private double test.Computer.frequency
private int test.Computer.RAM
private int test.Computer.HardDisk
private java.lang.String test.Computer.CPU

Computer类中的方法:
public java.lang.String test.Computer.toString()
public void test.Computer.setHardDisk(int)
public double test.Computer.getFrequency()
public void test.Computer.setRAM(int)
public void test.Computer.setFrequency(double)
public java.lang.String test.Computer.getCPU()
public void test.Computer.setCPU(java.lang.String)
public int test.Computer.getHardDisk()
public int test.Computer.getRAM()
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 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()

复制后的对象:
主频:2.5MHz 内存:4GB 硬盘:450GB CPU:Inter

4. 测试代码四数组类
java.lang.reflect 包中 Array 类提供了使用反射动态创建和访问 Java 数组的方法。 数组作为一个对象,
可以通过反射来查看其各个属性信息以及类型名

package test;
import java.lang.reflect.Array;
public class ReflectTest2 {

	public static void main(String[] args) {
		int[]array = new int[10];
		Class c1 = array.getClass();//获得整数数组Class类对象c1
		System.out.println("int数组的类型名:"+c1.getName());
		Class c2 = c1.getComponentType();//获得数组类型的Class对象c2
		System.out.println("int数组的类名:"+c2.getName());
		Object obj = Array.newInstance(int.class, 10);//使用Array类动态创建数组obj
		for(int i=0;i<10;i++){//对数组进行赋值
			Array.setInt(obj, i, i*10);
		}
		System.out.println("数组元素值:");
		
		for(int i=0;i<10;i++){//获得数组值
			System.out.print(Array.getInt(obj, i)+" ");
		}

	}

}

运行结果:
int数组的类型名:[I
int数组的类名:int
数组元素值:
0 10 20 30 40 50 60 70 80 90

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值