1类的加载连接和初始化

1.1类的加载过程

类的加载过程简单为分为三步:加载->连接->初始化


1.2类的加载器

1.2.1类的加载机制

  • 全盘加载:

    使用一个类负责加载一个Class文件,该Class依赖和负责的Class都由这个类加载器负责加载
  • 父类加载:

    先让这个类的父类加载器加载这个类,只有当这个父加载器无法加载时候,才从自己的类路径中加载该类
  • 缓存机制:

    所有被加载过的类都会被缓存,当程序需要某个类的时候,类加载器先从缓冲区寻找这个类,只有当这个类在缓存区不存在时候,才会读取对应的二进制文件,转换为Class对象,所以每次修改了Class后,需要重启JVM才能生效

加载器的继承的顺序,其中自定义的加载器通过继承ClassLoader来实现:

依照这个顺序,可以得到一个类加载的顺序


1.通过反射获得类的信息

package com.liyue.studycode.classreflect;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; @Retention(value = RetentionPolicy.RUNTIME)
@interface Anno{}
@SuppressWarnings(value = "unused")
public class BaseClass {
//declare a private constructor.
private BaseClass(){}; //decalre a public constructor
public BaseClass(int id){
System.out.println("excute a public constructor");
} //delcare a void function
public void fun(){
System.out.println("excute a void function");
}; //declare a function with paramter
public void test(String name){
System.out.println("excute a function with paramter: " + name);
} }
package com.liyue.studycode.classreflect;

import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.Arrays; public class RefectMain { public static void main(String[] args) throws NoSuchMethodException, SecurityException {
//get class's object
Class<BaseClass> cl = BaseClass.class; //get all public constructor
Constructor[] constructor = cl.getDeclaredConstructors();
System.out.println("All of BaseClass's constuctor:");
for(Constructor c : constructor){
System.out.println(c);
} //get all public method
Method[] method = cl.getMethods();
System.out.println("All of BaseClass's constuctor:");
for(Method m : method){
System.out.println(m);
} //get designated method
System.out.println("BaseClass's function with parameter named"
+ "test" + cl.getMethod("test", String.class) ); //get all annotation of BaseClass
Annotation[] an = cl.getAnnotations();
System.out.println("All annotation of BaseClass:");
for(Annotation a : an){
System.out.println(a);
} //get @SuppressWarnings
System.out.println("BaseClass's SuppressWarnings:"
+ Arrays.toString(cl.getAnnotationsByType
(SuppressWarnings.class))); //get package
System.out.println("BaseClass's package:"
+ cl.getPackage());
} }

2.Java 8新增的方法参数反射

如果将上例BaseClass.test方法改造一下:

public void test(String name, int num){
System.out.println("excute a function with paramter: " + name);
}

那么可以这么获取参数

Class<BaseClass> cl = BaseClass.class;
Method m = cl.getMethod("test", String.class, int.class);
Parameter[] ps = m.getParameters();
System.out.println(m.getParameterCount());
for(Parameter p : ps){
System.out.println(p.getName());
System.out.println(p.getType());
System.out.println(p.getParameterizedType());
}

3.通过反射操作对象

3.1创建对象

3.1.1使用newInstance方法

package com.liyue.studycode.objectfactory;

import java.io.FileInputStream;
import java.util.HashMap;
import java.util.Properties; public class ObjectFactory {
//declare a map to save object
private HashMap<String, Object> objectPool = new HashMap<>(); //declare function to new class,return object by class name
private Object createObject(String targetClassNmae)
throws Exception{
Class<?> cl = Class.forName(targetClassNmae);
return cl.newInstance();
} //read property file
public void initObjectPool(String fileName)
throws Exception{
Properties pRead = new Properties();
pRead.load(new FileInputStream(fileName));
for(String name : pRead.stringPropertyNames()){
objectPool.put(name, createObject(pRead.getProperty(name)));
}
} //return object of Map
public Object getObject(String name){
return objectPool.get(name);
}
}

定义一个属性文件,保存需要读取的信息

a = java.util.Date
b = javax.swing.JFrame
package com.liyue.studycode.objectfactory;

public class ObjectFactoryPrint {

    public static void main(String[] args) {
ObjectFactory of = new ObjectFactory();
try {
of.initObjectPool("Properties//myclassrelectconfig.ini");
System.out.println(of.getObject("a"));
System.out.println(of.getObject("b"));
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

3.1.2使用Constructor创建

try {
Class<?> cl = Class.forName("javax.swing.JFrame");
Constructor c = cl.getConstructor(String.class);
Object obj = c.newInstance("哈哈");
System.out.println(obj); } catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

3.2调用方法

package com.liyue.studycode.objectfactory;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method; public class ObjectFactoryPrint { public static void main(String[] args) throws Exception{
try {
//call method forName
Class<?> cl = Class.forName("javax.swing.JFrame");
//get constructor
Constructor c = cl.getConstructor(String.class);
//get instance of JFrame
Object obj = c.newInstance("");
//get method setTitle
Method md = cl.getMethod("setTitle", String.class);
//call invoke
md.invoke(obj, "哈哈");
System.out.println(obj); } catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

3.3访问成员变量

package com.liyue.studycode.fieldreflect;

import java.lang.reflect.Field;

public class FieldReflectPrint {

    public static void main(String[] args)
throws Exception{
Emploee e = new Emploee();
Class<?> cl = e.getClass();
//getDeclaredField get field of the class
/*get name*/
Field nameField = cl.getDeclaredField("name");
//Set the accessible flag for this object
nameField.setAccessible(true);
//set new value
nameField.set(e, "张三");
/*get age*/
Field agefield = cl.getDeclaredField("age");
//Set the accessible flag for this object
agefield.setAccessible(true);
//set new value
agefield.set(e, 29); System.out.println(e); }
}

3.4获取数组

4.使用反射生成JDK动态代理

4.1创建动态代理

package com.liyue.study.dynamicobject;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method; public class MyInvokationHandler implements InvocationHandler {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if(args != null){
System.out.println("下面是执行该方法时候传入的实参:");
for (Object v : args) {
System.out.println(v);
}
}
else{
System.out.println("调用该方法没有实参。");
}
return null;
} }
package com.liyue.study.dynamicobject;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy; public class DynamicObjectPrint {
public static void main(String[] args) throws Exception{
InvocationHandler handler = new MyInvokationHandler();
//使用InvocationHandler生成一个动态对象
Person p = (Person)Proxy.newProxyInstance(Person.class.getClassLoader()
, new Class[]{Person.class}
, handler);
p.walk();
p.sayHello("李四");
}
}

4.2动态代理和AOP

package com.liyue.studycode.aop;

public interface Bird {
//definition two abstract function
void info();
void fly();
}
package com.liyue.studycode.aop;

public class Duck implements Bird {

    @Override
public void info() {
// TODO Auto-generated method stub
System.out.println("I am a duck!");
} @Override
public void fly() {
// TODO Auto-generated method stub
System.out.println("I can fly!");
}
}
package com.liyue.studycode.aop;

public class BirdUtil {
//This is the first simulation function
public void fun1(){
System.out.println("This is birdutil function 1!");
}
//This is the second simulation function
public void fun2(){
System.out.println("This is birdutil function 2!");
}
}
package com.liyue.studycode.aop;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method; public class MyInvocationHandler implements InvocationHandler {
//The object need to agented
private Object target;
//setter
public void setTarget(Object target) {
this.target = target;
} @Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Exception {
BirdUtil bu = new BirdUtil();
//simulate the first function
bu.fun1();
//use target to excute method
Object result = method.invoke(target, args);
//simulate the second function
bu.fun2(); return result;
} }
package com.liyue.studycode.aop;

import java.lang.reflect.Proxy;

import com.liyue.studycode.aop.MyInvocationHandler;

public class MyProxy {
public static Object getProxy(Object target)
throws Exception{
//create a MyInvocationHandler
MyInvocationHandler mih = new MyInvocationHandler();
//set target to mih
mih.setTarget(target); return Proxy.newProxyInstance(target.getClass().getClassLoader()
, target.getClass().getInterfaces()
, mih);
}
}

package com.liyue.studycode.aop;

import com.liyue.study.dynamicobject.MyProxy;

public class AopPrint {

    public static void main(String[] args)
throws Exception {
//create a object of Duck
Bird target = new Duck();
Bird b = (Bird)MyProxy.getProxy(target);
b.info();
b.fly();
} }

有参构造的调用

有一个带参构造:

package pers.liyue.generic.test;

public class ReflectTest {
public int num = 0;
public double size = 0.00;
private float bignum = 0; public ReflectTest(){
System.out.println("Create class!");
} public ReflectTest(int numb){
System.out.println("Create class with args!" + numb);
}
}

调用时候不能用默认的newInstance

public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
ReflectTest rt = new ReflectTest();
rt.Fun1();
//无参构造调用
Class c = Class.forName("pers.liyue.generic.test.ReflectTest");
ReflectTest o = (ReflectTest)c.newInstance();
//有参构造调用
Constructor ccc = c.getConstructor(new Class[]{int.class});
ReflectTest b = (ReflectTest)ccc.newInstance(new Object[]{1});
}

24.类的加载机制和反射.md的更多相关文章

  1. Java基础_类的加载机制和反射

    类的使用分为三个步骤: 类的加载->类的连接->类的初始化 一.类的加载 当程序运行的时候,系统会首先把我们要使用的Java类加载到内存中.这里加载的是编译后的.class文件 每个类加载 ...

  2. jvm系列(一):java类的加载机制

    java类的加载机制 1.什么是类的加载 类的加载指的是将类的.class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在堆区创建一个java.lang.Class对象,用来封装 ...

  3. jvm系列 (五) ---类的加载机制

    类的加载机制 目录 jvm系列(一):jvm内存区域与溢出 jvm系列(二):垃圾收集器与内存分配策略 jvm系列(三):锁的优化 jvm系列 (四) ---强.软.弱.虚引用 我的博客目录 什么是类 ...

  4. 深入java虚拟机学习 -- 类的加载机制

    当看到"类的加载机制",肯定很多人都在想我平时也不接触啊,工作中无非就是写代码,不会了可以百度,至于类,jvm是怎么加载的我一点也不需要关心.在我刚开始工作的时候也觉得这些底层的内 ...

  5. JVM-01:类的加载机制

    本文从 纯洁的微笑的博客 转载 原地址:http://www.ityouknow.com/jvm.html 类的加载机制 1.什么是类的加载 类的加载指的是将类的.class文件中的二进制数据读入到内 ...

  6. Jvm类的加载机制

    1.概述 虚拟机加载Class文件(二进制字节流)到内存,并对数据进行校验.转换解析和初始化,最终形成可被虚拟机直接使用的Java类型,这一系列过程就是类的加载机制. 2.类的加载时机 类从被虚拟机加 ...

  7. JVM(1):Java 类的加载机制

    原文出处: 纯洁的微笑 java类的加载机制 1.什么是类的加载 类的加载指的是将类的.class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在堆区创建一个java.lang. ...

  8. 深入java虚拟机学习 -- 类的加载机制(续)

    昨晚写 深入java虚拟机学习 -- 类的加载机制 都到1点半了,由于第二天还要工作,没有将上篇文章中的demo讲解写出来,今天抽时间补上昨晚的例子讲解. 这里我先把昨天的两份代码贴过来,重新看下: ...

  9. 深入java虚拟机学习 -- 类的加载机制(三)

    类的初始化时机 在上篇文章中讲到了类的六种主动使用方式,反射是其中的一种(Class.forName("com.jack.test")),这里需要注意一点:当调用ClasLoade ...

随机推荐

  1. win10间歇性的找不到usb设备

    自从安装了win10,感觉掉了一个好大的坑. 比如win10经常找不到usb 设备,有时候过5-6分钟又有了.除了驱动的问题之外,有时候重启一下就好了. 今天又有一个小发现,笔记本为了省电,会把usb ...

  2. javasript-for循环

    先来个for循环的例子: var i=0,j=0; for(;i<10,j<6;i++,j++){ k=i+j; } console.log(k) 想知道会输出什么,首先得知道完整循环了多 ...

  3. windows服务没有及时响应启动或控制请求

    单击开始,单击运行,键入regedit,然后单击“确定”. 找到并单击以下注册表子项:HKEY_LOCAL_MACHINE——SYSTEM——CurrentControlSet——Control 在右 ...

  4. delphi EncdDecd.pas单元中Encoding方法出现#$D#$A的解决方法

    例如: s:= 'http://detail.tmall.com/item.htm?id=45545826531&abbucket=_AB-M129_B17&acm=03130.100 ...

  5. C# 自己动手实现Spy++(一)

    因为项目要用到获取其他程序的标题,就想到了用Spy++,但是它是一个工具,并没有C#的源代码,所以就想探索下他的原理,网上搜索了下spy++的源代码,找到了一篇:http://blog.csdn.ne ...

  6. RISC与CISCCPU构架

    RISC 精简指令集 CISC复杂指令集 CISC架构的代表: x86, C51 RISC架构的代码:arm, mips,powerpc, avr, pic 指令集的区别 首先从字面上理解就能知道, ...

  7. 用VirtualBox快速安装虚拟机virtual Machine(Win7+IE10)

    前端测试,经常需要各种环境, 用“Virtual Box + OVA文件”安装虚拟机, 是简单高效的一种方法,可以安装各种window和IE的版本.下面以IE10 + Win7为例说明. 1) 下载和 ...

  8. C# 如何提取字符串中的数字(小技巧)

    下面讲解如何在字符串当中抓取到数字 方法一.使用正则表达式 1.纯数字提取 1 string str = "提取123abc提取"; //我们抓取当前字符当中的123 2 stri ...

  9. Solr——从postgresql数据库导入数据

    1,配置准备 本文的前提是你已经配置好了solr,并新创建了一个core,我们下面都会按照前一篇文章中的core_demo为基础开始 2,修改soreconfig.xml 在soreconfig.xm ...

  10. centos7 安装Node.js并配置为全局可用

    本文Node.js版本为5.12.0,登录 https://nodejs.org/dist/v5.12.0/,需指定其他版本的话可以直接修改版本号进行登录. 为了方便使用tar命令对文件进行解压,我们 ...