J2EE从入门到入土04 Java反射

目录

什么是反射

加载 

验证

准备

解析

初始化

实例演练

实体类 

 测试代码


什么是反射

 JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制

在了解反射机制之前我们首先了解一下Java类加载的过程

加载 

加载是将类的.class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在堆区创建一个java.lang.Class对象,用来封装类在方法区内的数据结构。类的加载的最终产品是位于堆区中的Class对象,Class对象封装了类在方法区内的数据结构,并且向Java程序员提供了访问方法区内的数据结构的接口。 

验证

这是虚拟机安全的重要保障,JVM需要核检字节信息是符合Java虚拟机规范的,否则就被认为是VerifyError。这样就防止了恶意信息或者不合规的信息危害JVM的运行。

准备

准备阶段主要是为类变量(注意,不是实例变量)分配内存,并且赋予初值。 特别需要注意初值,不是代码中具体写的初始化的值,而是Java虚拟机根据不同变量类型的默认初始值。

解析

将常量池内的符号引用替换为直接引用的过程。

初始化

主要是对类变量初始化,是执行类构造器的过程。

反射机制的相关类

通过反射可访问的主要描述信息

组成部分

访问方法

返回值类型

说明

包路径

getPackage()

Package对象

获得该类的存放路径

类名称

getName()

String对象

获得该类的名称

继承类

getSuperclass()

Class对象

获得该类继承的类

实现接口

getInterfaces()

Class型数组

获得该类实现的所有接口

构造方法

getConstructors()

Constructor型数组

获得所有权限为public的构造方法

getConstructor(Class<?>...parameterTypes)

Constructor对象

获得权限为public的指定构造方法

getDealaredConstructors()

Constructor型数组

获得所有构造方法,按声明顺序返回

getDealaredConstructor(Class<?>...parameterTypes)

Constructor对象

获得指定的构造方法

方法

getMethods()

Method型数组

获取所有权限为public的方法

getMethod(String name,Class<?>...parametersTypes)

Method对象

获得权限为public的指定方法

getDeclareMethods()

Method型数组

获得所有方法,按声明顺序返回

getDeclareMethod(String name,Class<?>...parameterTypes)

Method对象

获得指定方法

成员变量

getFields()

Field型数组

获得所有权限为public的成员变量

getField(Sgtring name)

Field对象

获得权限为public的指定成员变量

getDeclaredFields()

Field型数组

获得所有成员变量,按声明顺序返回

getDeclaredField(String name)

Field对象

获得指定的成员变量

内部类

getClasses()

Class型数组

获得所有权限为public的内部类

getDeclaredClasses()

Class型数组

获得所有内部类

内部类的声明类

getDeclaringClass()

Class对象

如果该类为内部类,则返回它的成员类,否则返回null

 说明: 通过getFields()和getMethods()方法依次获得权限为public的成员变量和方法时,将包含从超类中继承到的成员变量和方法;而通过方法getDeclaredFields()和getDeclaredMethods()只能获得在本类中定义的所有成员变量和方

实例演练

        // 根据包名获取Class的对象
        Class<Student> clazz = (Class<Student>) Class.forName("com.zking.reflect.Student");
        // 2. 类.class
        Class clazz02 = Student.class;
        // 3. 对象.getClass()
        Student stu = new Student();
        Class clazz03 = stu.getClass(); 

实体类 

package com.zking.reflect;

public class Student {
	private String sid;

	private String sname;

	public Integer age;
	
	static{
		System.out.println("加载进jvm中!");
	}

	public Student() {
		super();
		System.out.println("调用无参构造方法创建了一个学生对象");
	}

	public Student(String sid) {
		super();
		this.sid = sid;
		System.out.println("调用带一个参数的构造方法创建了一个学生对象");
	}

	public Student(String sid, String sname) {
		super();
		this.sid = sid;
		this.sname = sname;
		System.out.println("调用带二个参数的构造方法创建了一个学生对象");
	}

	@SuppressWarnings("unused")
	private Student(Integer age) {
		System.out.println("调用Student类私有的构造方法创建一个学生对象");
		this.age = age;
	}

	public String getSid() {
		return sid;
	}

	public void setSid(String sid) {
		this.sid = sid;
	}

	public String getSname() {
		return sname;
	}

	public void setSname(String sname) {
		this.sname = sname;
	}

	public void hello() {
		System.out.println("你好!我是" + this.sname);
	}

	public void hello(String name) {
		System.out.println(name + "你好!我是" + this.sname);
	}

	@SuppressWarnings("unused")
	private Integer add(Integer a, Integer b) {
		return new Integer(a.intValue() + b.intValue());
	}

	@Override
	public String toString() {
		return "Student [sid=" + sid + ", sname=" + sname + ", age=" + age + "]";
	}
	
}

 测试代码

package com.zking.reflect;

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

public class Test {

	@SuppressWarnings({ "unchecked", "unused" })
	public static void main(String[] args) throws Exception {
		// 根据包名获取Class的对象
		Class<Student> clazz = (Class<Student>) Class.forName("com.zking.reflect.Student");
		// 2. 类.class
		Class clazz02 = Student.class;
		// 3. 对象.getClass()
		Student stu = new Student();
		Class clazz03 = stu.getClass();
		//获得包名目录
		Package package1 = clazz03.getPackage();
		System.out.println(package1);
		
		System.out.println(clazz);
		System.out.println(clazz02);
		System.out.println(clazz03);
		
		//通过反射实例化对象如果有参数就在后面括号填入参数类型,下面是无参构造
		Constructor<Student> c1 = clazz.getConstructor();
		Student stu01 = c1.newInstance();
		stu01.setSname("ls");//调用属性方法赋值
		System.out.println(stu01);
		
		
		//通过反射获取私无参有构造
		Constructor<Student> c2 = clazz.getDeclaredConstructor();
		c2.setAccessible(true);//获取权限操作符
		Student stu02 = c2.newInstance();
		
		System.out.println(stu02);
		
		//通过反射获取私有有参构造
		Constructor<Student> c3 = clazz.getDeclaredConstructor(String.class);//填入参数类型
		c3.setAccessible(true);//获取权限操作符
		Student stu03 = c3.newInstance("11");//实例填入参数
		
		System.out.println(stu03);
		
		
		//获取方法
		Method method = clazz.getMethod("hello");//根据方法名获取方法对象
		stu03.setSname("hh");
		method.invoke(stu03);//调用了stu03的hello方法
		
		//获取私有方法
		Method method2 = clazz.getDeclaredMethod("add",Integer.class,Integer.class);//根据对象名获得方法,根据方法传入对应的参数
		method2.setAccessible(true);
		int c = (int)method2.invoke(stu03, 11,11);//根据对象调用对应的方法,传入参数
		System.out.println(c);//打印返回结果
		
		//反射读写的属性
		Field f = clazz.getField("age");//根据对象属性名获得属性
		f.set(stu03, 99);//传入对象和要设置的值
		System.out.println(stu03);
		System.out.println(f.get(stu03));
		
		//反射读写的私有属性
		Field f01 = clazz.getDeclaredField("sname");//根据对象属性名获得属性
		f01.setAccessible(true);
		f01.set(stu03, "xxxx");//传入对象和要设置的值
		System.out.println(stu03);
	}
}

 结果:

加载进jvm中!
调用无参构造方法创建了一个学生对象
package com.zking.reflect
class com.zking.reflect.Student
class com.zking.reflect.Student
class com.zking.reflect.Student
调用无参构造方法创建了一个学生对象
Student [sid=null, sname=ls, age=null]
调用无参构造方法创建了一个学生对象
Student [sid=null, sname=null, age=null]
调用带一个参数的构造方法创建了一个学生对象
Student [sid=11, sname=null, age=null]
你好!我是hh
22
Student [sid=11, sname=hh, age=99]
99
Student [sid=11, sname=xxxx, age=99]

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值