Java 类加载机制和反射机制

Java 类加载机制和反射机制

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

开发工具与关键技术:

作者:陈剑波

撰写时间:2019年08月08日

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

一、Java类加载机制

jvm把class文件加载到内存,并对数据进行校验、解析和初始化,最终形成jvm可以直接使用的java类型的过程。

Java类的生命周期:加载-》验证-》准备-》解析-》初始化-》使用-》卸载

(1)加载:
         将class文件字节码内容加载到内存中,并将这些静态数据转换成方法区中的运行时数据结构,在堆中生成一个代表这个类的java.lang.Class对象,作为方法区类数据的访问入口。

(2)链接: 将java类的二进制代码合并到jvm的运行状态之中的过程。

1. 验证:确保加载的类信息符合jvm规范,没有安全方面的问题。

2. 准备:正式为类变量(static变量)分配内存并设置类变量初始值的阶段,这些内存都将在方法区中进行分配。

 3.解析:虚拟机常量池内的符号引用替换为直接引用的过程。(比如String s ="aaa",转化为 s的地址指向“aaa”的地址)

(3)初始化:
        初始化阶段是执行类构造器方法的过程。类构造器方法是由编译器自动收集类中的所有类变量的赋值动作和静态语句块(static块)中的语句合并产生的。
             1.当初始化一个类的时候,如果发现其父类还没有进行过初始化,则需要先初  

             始化其父类的初始化。
             2.虚拟机会保证一个类的构造器方法在多线程环境中被正确加锁和同步。
             3.当访问一个java类的静态域时,只有真正声明这个静态变量的类才会被初始

             化。

示例代码:

import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

/**
 * @author KO.ZERO 反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;
 *         对于任意一个对象,都能够调用它的任意一个方法和属性;
 */
public class ReflectDemo implements Serializable {
	public static void main(String[] args) throws Exception {
		// 通过一个对象获得完整的包名和类名
		ReflectDemo demo = new ReflectDemo();
		// getClass():返回此对象的运行时类。返回的类对象是由所表示类的静态同步方法锁定的对象。
		// getName():返回由这个类对象表示的实体(类、接口、数组类、基本类型或void)的名称,作为字符串。
		System.out.println("获得对象完整的包名和类名" + demo.getClass().getName());
		// 实例化Class类对象
		Class<?> class1 = null;
		Class<?> class2 = null;
		Class<?> class3 = null;
		class1 = Class.forName("com.ko2.demo.ReflectDemo");
		class2 = new ReflectDemo().getClass();
		class3 = ReflectDemo.class;
		Class<?> class4 = ReflectDemo.class.getClassLoader().loadClass(
				"com.ko2.demo.ReflectDemo");
		System.out.println("类名:" + class1.getName());
		System.out.println("类名:" + class2.getName());
		System.out.println("类名:" + class3.getName());
		System.out.println("类名:" + class4.getName());
		// 获取对象的父类与实现的接口
		// 取得父类
		// getSuperclass():返回表示该类表示的实体(类、接口、基本类型或void)的超类。如果该类表示对象类、接口、基本
		// 类型或void,则返回null。如果此对象表示数组类,则返回表示对象类的类对象。
		Class<?> parentClass = class1.getSuperclass();
		System.out.println("class1的父类为:" + parentClass.getName());
		// 获取所有的接口
		Class<?> intes[] = class1.getInterfaces();
		System.out.println("class1实现的接口有:");
		for (int i = 0; i < intes.length; i++) {
			System.out.println((i + 1) + ":" + intes[i].getName());
		}
		// 通过反射机制调用某个类的方法
		// 调用TestReflect类中的reflect1方法
		Method method = class1.getMethod("reflect1");
		method.invoke(class1.newInstance());
		// Java 反射机制 - 调用某个类的方法1.
		// 调用TestReflect的reflect2方法
		method = class1.getMethod("reflect2", int.class, String.class);
		// Java 反射机制 - 调用某个类的方法2.
		method.invoke(class1.newInstance(), 24, "列小龙");
		//获取某个类的全部属性
		Class<?> class6 = Class.forName("com.ko2.demo.Person");
		// 取得本类的全部属性
		Field[] field = class6.getDeclaredFields();
		for (int i = 0; i < field.length; i++) {
			// 权限修饰符
			int mo = field[i].getModifiers();
			String priv = Modifier.toString(mo);
			// 属性类型
			Class<?> type = field[i].getType();
			System.out.println(priv + " " + type.getName() + " "
					+ field[i].getName() + ";");
		}
		//获取某个类的全部方法
		 Method method2[] = class1.getMethods();
	        for (int i = 0; i < method2.length; ++i) {
	            Class<?> returnType = method2[i].getReturnType();
	            Class<?> para[] = method2[i].getParameterTypes();
	            int temp = method2[i].getModifiers();
	            System.out.print(Modifier.toString(temp) + " ");
	            System.out.print(returnType.getName() + "  ");
	            System.out.print(method2[i].getName() + " ");
	            System.out.print("(");
	            for (int j = 0; j < para.length; ++j) {
	                System.out.print(para[j].getName() + " " + "arg " + j);
	                if (j < para.length - 1) {
	                    System.out.print(",");
	                }
	            }
	            //getExceptionTypes():返回一个类对象数组,该数组表示由该方法对象表示的底层方法声明要抛出的异常的类型。
	            //如果方法在其抛出子句中声明没有异常,则返回长度为0的数组。
	            Class<?> exce[] = method2[i].getExceptionTypes();
	            if (exce.length > 0) {
	                System.out.print(") throws ");
	                for (int k = 0; k < exce.length; ++k) {
	                    System.out.print(exce[k].getName() + " ");
	                    if (k < exce.length - 1) {
	                        System.out.print(",");
	                    }
	                }
	            } else {
	                System.out.print(")");
	            }
	            System.out.println();
	        }
	}

	public void reflect1() {
		System.out.println("Java 反射机制 - 调用某个类的方法1.");
	}

	public void reflect2(int age, String name) {
		System.out.println("Java 反射机制 - 调用某个类的方法2.");
		System.out.println("age -> " + age + ". name -> " + name);
	}
}

class Person {
	private String name;
	private int age;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) throws Exception {
		if (age < 0 || age > 120) {
			System.out.println("年龄不符合要求");
			return;
		} else {
			this.age = age;
		}
	}
}

运行结果:

获得对象完整的包名和类名com.ko2.demo.ReflectDemo
类名:com.ko2.demo.ReflectDemo
类名:com.ko2.demo.ReflectDemo
类名:com.ko2.demo.ReflectDemo
类名:com.ko2.demo.ReflectDemo
class1的父类为:java.lang.Object
class1实现的接口有:
1:java.io.Serializable
Java 反射机制 - 调用某个类的方法1.
Java 反射机制 - 调用某个类的方法2.
age -> 24. name -> 列小龙
private java.lang.String name;
private int age;
public static void  main ([Ljava.lang.String; arg 0) throws java.lang.Exception 
public void  reflect1 ()
public void  reflect2 (int arg 0,java.lang.String arg 1)
public final void  wait (long arg 0,int arg 1) throws java.lang.InterruptedException 
public final native void  wait (long arg 0) throws java.lang.InterruptedException 
public final void  wait () throws java.lang.InterruptedException 
public boolean  equals (java.lang.Object arg 0)
public java.lang.String  toString ()
public native int  hashCode ()
public final native java.lang.Class  getClass ()
public final native void  notify ()
public final native void  notifyAll ()

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值