java 类的加载及反射机制

一,类的加载,连接,初始化

一个类被加载到JVM需要三个步骤:加载,链接,初始化

1,先说下加载过程

2,连接

注意连接过程分为三个阶段,验证,准备,解析

3,初始化

这里注意:类的加载过程,先加载静态代码块,其次是代码块,然后是构造函数

静态成员之间级别一样,因此谁在前,谁最先被加载

二,反射机制

1,先理解下反射

2,为什么要使用反射

可能以上叙述依然很抽象,下面我们用具题代码说明

在开始代码之前我们要先,明白一个对象 java.lang.Class

我们可以这样想,java程序在运行前,会把一些类,接口,以及各种资源加载到JVM(java虚拟机)中,如果一个程序有N个类,N个接口,那么JVM在运行程序是就要,一个一个的去找到这些类,接口,如果虚拟机真的运用这种机制,没使用一个类,或者接口都要去遍历所有的接口和类,那么虚拟机要做的工作就太多的,当然java的设计人员也不会允许这样的事情发生。其实在程序加载时,虚拟机会记录每一个加载的类以及接口的具体信息,包括他们的地址,而这些信息就放在了一个叫做Class的对象中,因在虚拟机用到具体的类和接口等资源时,只要通过Class就能够快速访问到(我们可以把Class想象成一张记录了所有资源的文档)

代码部分

1,//基类

package com.day17.work;

public class People {

//属性
private String pName;
private String pIdentifyId;
private String pGender;
//默认构造函数

//方法
public void eat()
{}

public void sleep()
{}

//get/set方法
public String getpName() {
return pName;
}
public void setpName(String pName) {
this.pName = pName;
}
public String getpIdentifyId() {
return pIdentifyId;
}
public void setpIdentifyId(String pIdentifyId) {
this.pIdentifyId = pIdentifyId;
}
public String getpGender() {
return pGender;
}
public void setpGender(String pGender) {
this.pGender = pGender;
}

}

2,

//子类,继承了People,以上这两个类是为最后测试准备

package com.day17.work;

public class Student extends People implements Runnable{

private String sSno;
private String sClass;
private String sScore;

public Student()
{

}
public Student(String sSno) {
super();
this.sSno = sSno;
}

public Student(String sSno, String sClass, String sScore) {
super();
this.sSno = sSno;
this.sClass = sClass;
this.sScore = sScore;
}
@Override
public void run() {
// TODO Auto-generated method stub
//这里实现了Runnable,具体方法不作处理
}
public String getsSno() {
return sSno;
}
public void setsSno(String sSno) {
this.sSno = sSno;
}
public String getsClass() {
return sClass;
}
public void setsClass(String sClass) {
this.sClass = sClass;
}
public String getsScore() {
return sScore;
}
public void setsScore(String sScore) {
this.sScore = sScore;
}

public void student(String couse)
{}

public void playGame(String gameName)
{
System.out.println(this.getpName()+" Palying "+gameName);
}

public void watchTv()
{}

public void clickCode(String courseName,int lines)
{
System.out.println(this.getpName()+" Click " +courseName+" code "+lines+" lines");
}
}

3,

package com.day17.work;

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

public class ReflectionDome {
/*本程序输出时并未对输出结果做具体的排版,但应该涉及的方法都有涉及,每一块的
* 具体功能,代码中都有注释
* */
public static void main(String[] args) {
// TODO Auto-generated method stub

//下面方法,根据ppt一个一个来
//初始化得到对应的Class
Class<?> studentClass=Student.class;

//1,构造器
//返回此Class对象对应类的指定public构造器
System.out.println("1,关于Class的构造器");
try {
Constructor<?> con=studentClass.getConstructor(String.class);
System.out.println("返回此Class对象对应类的指定public构造器");
System.out.println(Modifier.toString(con.getModifiers())+" "+con.getName());
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

//返回此类对象对应类的所有构造器,与权限无关
Constructor<?>[] cons=studentClass.getDeclaredConstructors();
System.out.println();
System.out.println("返回此类对象对应类的所有构造器,与权限无关");
for(Constructor<?> con:cons)
{
System.out.println(con.getName());
Class<?>[] params=con.getParameterTypes();
System.out.println("构造函数参数类型");
for(Class<?> type:params)
{
//这里说有参数和类名不做任何排版上的处理,仅仅输出
System.out.println(type.getTypeName());
}

}

//2,获取Class对象对应类所包含的方法
//返回所有public方法

Method[] methods=studentClass.getMethods();
//循环输出
System.out.println();
System.out.println("2,获取Class对象对应类所包含的方法");
for(Method method:methods)
{
System.out.println("所有函数的方法名");
System.out.println(method.getName());
}

//返回指定的public方法
try {
System.out.println();
System.out.println("返回指定的public方法");
Method method=studentClass.getMethod("playGame", String.class);
System.out.println(Modifier.toString(method.getModifiers()));
System.out.println(method.getGenericReturnType());
System.out.println(method.getName());
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

//3,获取Class对应类所包含的Field,返回所有Field,与权限无关
System.out.println();//为了看着分明一点
System.out.println("3,获取Class对应类所包含的Field");
Field[] fields=studentClass.getDeclaredFields();
//又是遍历
for(Field field:fields)
{
try {
System.out.println(Modifier.toString(field.getModifiers())+" "+field.getGenericType()+" "+field.getName());
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

//4,获取Class对象对应类的相关类、接口等
System.out.println();//为了看着分明一点
System.out.println("4,获取Class对象对应类的相关类、接口等");
System.out.println("返回实现的全部接口");
System.out.println(studentClass.getInterfaces()[0].getName());
//因为实现了一个借口,所以偷个懒,不再遍历

System.out.println("返回该Class对象对应类的超类的Class对象");
System.out.println(studentClass.getSuperclass().getName());

}

//5,获取Class对象对应类的修饰符、所在包、类名等基本信息

System.out.println();
System.out.println("5,获取Class对象对应类的修饰符、所在包、类名等基本信息");

//返回此类或接口的所有修饰符。
//如public、protected、private、final、static、abstract等对应的常量组成,
//返回的整数应当使用Modifier工具类的方法来解码,才可获取真实的修饰符

System.out.println(Modifier.toString(studentClass.getModifiers()));

//获取此类的包
System.out.println("获取包名 "+studentClass.getPackage());

//返回此Class对象所表示的类的名称
System.out.println("Class对象所表示的类的名称 "+studentClass.getName());

//6,判断该类是否为接口、枚举类型等
System.out.println();
System.out.println("6,判断该类是否为接口、枚举类型等");
Class<?> run=Runnable.class;//这里使用JDK提供的接口进行测试
System.out.println("是否表示一个接口 "+run.isInterface());

//7.使用Class对象的newInstance()方法来创建该Class对象对应类的实例,
System.out.println();
System.out.println("使用Class对象的newInstance()方法来创建该Class对象对应类的实例,");
//这里创建一个Student对象,并测试他的一对get/set方法,然后调用调用一个方法作为事例,其他不列举

try {
//有一点需要注意,调用此方法newInstance()创建实例,Student必须用于一个无参的构造函数。
Student stu=(Student) studentClass.newInstance();//这里得到了一个Student
//实例,与new方法得到的实例等效,下面操作,不再过多赘述
stu.setpName("张三");
System.out.println(stu.getpName());

stu.playGame("LOL");
stu.clickCode("java",10000);
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

}
}

好了,就先到这了(如果发现代码中有问题,或者是哪里理解有问题,还望不吝赐教!!!)

时间: 2024-08-04 22:20:37

java 类的加载及反射机制的相关文章

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

java类的加载机制 原文:http://www.cnblogs.com/ityouknow/p/5603287.html 1.什么是类的加载 类的加载指的是将类的.class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在堆区创建一个java.lang.Class对象,用来封装类在方法区内的数据结构.类的加载的最终产品是位于堆区中的Class对象,Class对象封装了类在方法区内的数据结构,并且向Java程序员提供了访问方法区内的数据结构的接口. 类加载器并不需要等到某个

跟王老师学反射(二):Java类的加载、连接和初始化

跟王老师学反射(二):Java类的加载.连接和初始化 主讲教师:王少华   QQ群号:483773664 学习内容: 了解类的加载.连接和初始化 一.类的生命周期 当我们编写一个java的源文件后,经过编译会生成一个后缀名为class的文件,这种文件叫做字节码文件,只有这种字节码文件才能够在java虚拟机中运行,java类的生命周期就是指一个class文件从加载到卸载的全过程.一个java类的完整的生命周期会经历加载.连接.初始化.使用.和卸载五个阶段,当然也有在加载或者连接之后没有被初始化就直

Java类的加载、链接和初始化

一.Java的类加载机制回顾与总结: 我们知道一个Java类要想运行,必须由jvm将其装载到内存中才能运行,装载的目的就是把Java字节代码转换成JVM中的java.lang.Class类的对象.这样Java就可以对该对象进行一系列操作,装载过程有两个比较重要的特征:层次组织结构和代理模式.层次组织结构指的是每个类加载器都有一个父类加载器,通过getParent()方法可以获取到.类加载器通过这种父亲-后代的方式组织在一起,形成树状层次结构.代理模式则指的是一个类加载器既可以自己完成Java类的

黑马程序员————java中类的加载、反射、动态代理、枚举

------<a href="http://www.itheima.com" target="blank">Java培训.Android培训.iOS培训..Net培训</a>.期待与您交流! ------- 类的加载.反射.动态代理.枚举 一.类的加载 当程序要使用某个类时,如果该类还未被加载到内存中,则系统会通过加载,连接,初始化三步来实现对这个类进行初始化. 1.加载: 就是指将class文件读入内存,并为之创建一个Class对象 ★★

别翻了,这篇文章绝对让你深刻理解java类的加载以及ClassLoader源码分析【JVM篇二】

目录 1.什么是类的加载(类初始化) 2.类的生命周期 3.接口的加载过程 4.解开开篇的面试题 5.理解首次主动使用 6.类加载器 7.关于命名空间 8.JVM类加载机制 9.双亲委派模型 10.ClassLoader源码分析 11.自定义类加载器 12.加载类的三种方式 13.总结 14.特别注意 @ 前言 你是否真的理解java的类加载机制?点进文章的盆友不如先来做一道非常常见的面试题,如果你能做出来,可能你早已掌握并理解了java的类加载机制,若结果出乎你的意料,那就很有必要来了解了解j

Java类的加载 链接 初始化

原文地址 Java类的加载.链接和初始化.Java字节代码的表现形式是字节数组(byte[]),而Java类在JVM中的表现形式是java.lang.Class类的对象.一个Java类从字节代码到能够在JVM中被使用,需要经过加载.链接和初始化这三个步骤.这三个步骤中,对开发人员直接可见的是Java类的加载,通过使用Java类加载器(class loader)可以在运行时刻动态的加载一个Java类:而链接和初始化则是在使用Java类之前会发生的动作.本文会详细介绍Java类的加载.链接和初始化的

java 类的加载,链接,初始化

本篇的话题,讨论Java类的加载.链接和初始化.Java字节代码的表现形式是字节数组(byte[]),而Java类在JVM中的表现形式是java.lang.Class类的对象.一个Java类从字节代码到能够在JVM中被使用,需要经过加载.链接和初始化这三个步骤.这三个步骤中,对开发人员直接可见的是Java类的加载,通过使用Java类加载器(class loader)可以在运行时刻动态的加载一个Java类:而链接和初始化则是在使用Java类之前会发生的动作.本文会详细介绍Java类的加载.链接和初

【Java基础】Java类的加载和对象创建流程的详细分析

相信我们在面试Java的时候总会有一些公司要做笔试题目的,而Java类的加载和对象创建流程的知识点也是常见的题目之一.接下来通过实例详细的分析一下. 实例问题 实例代码 Parent类 1 package mytest.javaBase; 2 3 public class Parent { 4 int a = 10; 5 static int b = 11; 6 // 静态代码块 7 static { 8 System.out.println("Parent静态代码块:b=" + b)

JAVA类的加载顺序

JAVA类的加载顺序 JAVA中类的初始化规则是:先初始化static成员变量和static块,再初始化non-static成员变量和non-static块,最后初始化构造函数. 例1: package demo; /** * 此类主要介绍java类的加载顺序 * */ public class TestOrder { public static int k = 0; public static TestOrder t1 = new TestOrder("t1"); public st