Java中Class类工作原理详解
java的Class类有哪些

java的Class类有哪些java的Class类有哪些Class类是在Java语言中定义一个特定类的实现。
java的Class 类有哪些呢?下面店铺为大家解答一下,希望能帮到大家!Class 类是在Java语言中定义一个特定类的实现。
一个类的定义包含成员变量,成员方法,还有这个类实现的接口,以及这个类的父类。
Class类的对象用于表示当前运行的Java 应用程序中的类和接口。
比如:每个数组均属于一个Class 类对象,所有具有相同元素类型和维数的数组共享一个Class 对象。
基本的Java 类型(boolean, byte, char, short, int, long, float 和 double) 和 void 类型也可表示为 Class 对象。
一,class类有什么用?class类的实例表示java应用运行时的类(class ans enum)或接口(interface and annotation)(每个java类运行时都在JVM里表现为一个class对象,可通过类名.class,类型.getClass(),Class.forName("类名")等方法获取class对象)。
数组同样也被映射为为class 对象的一个类,所有具有相同元素类型和维数的数组都共享该Class 对象。
基本类型boolean,byte,char,short,int,long,float,double和关键字void同样表现为 class 对象。
二,class类的特征class类没有公有的构造方法,它由JVM自动调用(在new对象或者加载-classLoader时)。
下面的方法作用是打印出对象的class name:void printClassName(Object obj) {System.out.println("The class of " + obj +" is " + obj.getClass().getName());}同样可以根据class literal 获得class name:System.out.println("The name of class Foo is:"+Foo.class.getName());//你可以将Foo改为void尝试下。
Java运行时动态生成class

Java运⾏时动态⽣成class转载/article/0014617596492474eea2227bf04477e83e6d094683e0536000Java是⼀门静态语⾔,通常,我们需要的class在编译的时候就已经⽣成了,为什么有时候我们还想在运⾏时动态⽣成class呢?因为在有些时候,我们还真得在运⾏时为⼀个类动态创建⼦类。
⽐如,编写⼀个ORM框架,如何得知⼀个简单的JavaBean是否被⽤户修改过呢?以User为例:public class User {private String id;private String name;public String getId() {return id;}public void setId(String id) {this.id = id;}public String getName() {return name;}public void setName(String name) { = name;}}其实UserProxy实现起来很简单,就是创建⼀个User的⼦类,覆写所有setXxx()⽅法,做个标记就可以了:public class UserProxy extends User {private boolean dirty;public boolean isDirty() {return this.dirty;}public void setDirty(boolean dirty) {this.dirty = dirty;}@Overridepublic void setId(String id) {super.setId(id);setDirty(true);}@Overridepublic void setName(String name) {super.setName(name);setDirty(true);}}但是这个UserProxy就必须在运⾏时动态创建出来了,因为编译时ORM框架根本不知道User类。
classloader加载原理

classloader加载原理classloader是java中一个比较重要的类加载器,每一个程序和类都会存在一个classloader,classloader有三种主要的工作:加载类的二进制字节流、连接、初始化。
一、Classloader加载机制1、首先classloader会按照特定的方式去搜索类文件,当它找到了相应的类文件之后,它会将这个类文件转换成为二进制字节流,这里涉及到编译程序,classloader会使用编译程序将源程序编译成可执行文件。
2、接下来classloader会将这些二进制字节流存储在内存中,然后classloader会连接这些字节流,这一步是它将这些字节流组装成一个完整的类文件,这里涉及到类的加载,这些加载的类可以被访问,但是它们的代码还未被执行。
3、最后classloader会初始化这些加载的类,这一步就是它将这些类的代码执行,这里classloader会执行所有类变量的初始化,同时也会执行所有静态代码块的内容,最后我们就可以得到一个完整的类文件。
二、Classloader的三种类型1、Bootstrap Classloader:它是用来加载JRE的核心类的,它的实现是C++语言,它的加载范围是从<JAVA_HOME>lib下面开始,这个类加载器不需要程序员编写任何外部类。
2、Extension Classloader:它是用来加载扩展类的,从<JAVA_HOME>libext开始加载,它继承自Bootstrap Classloader,这种类加载器也不需要程序员手动编写任何外部类。
3、Application Classloader:它是用来加载程序类的,它继承自Extension Classloader,它从ClassPath(来自系统变量或者命令行参数)所指定的路径中加载类,但是它不会加载扩展类。
三、Classloader安全机制1、安全性验证:Classloader在加载类的时候会先验证这个类文件,检查它是否符合class文件格式,其次classloader会过滤掉由它本身加载的不安全的类,这涉及到安全管理器的配置,例如:可以设置它只能加载特定的域名下的类文件。
Java中泛型T和ClassT以及Class?的理解(转)

Java中泛型T和ClassT以及Class?的理解(转)注意:class是java的关键字, 在声明Java类时使⽤;Class类的实例表⽰Java应⽤运⾏时的类(class ans enum)或接⼝(interface and annotation)(每个Java类运⾏时都在JVM ⾥表现为⼀个Class对象,可通过类名.class,类型.getClass(),Class.forName("类名")等⽅法获取Class对象)。
数组同样也被映射为为Class对象的⼀个类,所有具有相同元素类型和维数的数组都共享该Class对象。
基本类型boolean,byte,char,short,int,long,float,double和关键字void同样表现为Class对象。
T bean ;Class<T> bean;Class<?> bean;单独的T代表⼀个类型,⽽Class<T>和Class<?>代表这个类型所对应的类Class<T>在实例化的时候,T要替换成具体类Class<?>它是个通配泛型,?可以代表任何类型<? extends T>受限统配,表⽰T的⼀个未知⼦类。
<? super T>下限统配,表⽰T的⼀个未知⽗类。
public T find(Class<T> clazz, int id);根据类来反射⽣成⼀个实例,⽽单独⽤T没法做到。
Object类中包含⼀个⽅法名叫getClass,利⽤这个⽅法就可以获得⼀个实例的类型类。
类型类指的是代表⼀个类型的类,因为⼀切皆是对象,类型也不例外,在Java使⽤类型类来表⽰⼀个类型。
所有的类型类都是Class类的实例。
getClass()会看到返回Class<?>。
JDK中,普通的Class.newInstance()⽅法的定义返回Object,要将该返回类型强制转换为另⼀种类型;但是使⽤泛型的Class<T>,Class.newInstance()⽅法具有⼀个特定的返回类型;参考:。
Java语言中的Class类

Java语⾔中的Class类基本概念在Object类中定义了以下的⽅法,此⽅法将被所有⼦类继承public final Class getClass()这个⽅法的返回值类型是⼀个Class类,此类是Java反射的源头,是实际上所谓反射从程序的运⾏结果来看也很好理解,即:可以通过对象反射求出类的名称。
对象照镜⼦后可以得到的信息:某个类的属性、⽅法和构造器、某个类到底实现了哪些接⼝。
对于每个类⽽⾔,JRE都为其保留⼀个不变的Class类型的对象。
⼀个Class对象包含了特定某个结构(class、interface、enum、annotation、primitive type、void)的有关信息。
Class本⾝也是⼀个类Class对象只能由系统建⽴对象⼀个加载的类在JVM中只会有⼀个Class实例⼀个Class对象对应的是⼀个加载到JVM中的⼀个.class⽂件每个类的实例都会记得⾃⼰是由哪个Class实例所⽣成通过Class可以完整地得到⼀个类中的所有被加载结构Class类是Reflection的根源,针对任何你想动态加载、运⾏的类,唯有先获得相应的Class对象。
Java中拥有Class对象的类型在Java语⾔中,⼀切皆是对象。
⽽对象主要分为两种,⼀种是普通类创建的实例对象,⼀种是Class类对象。
每个类运⾏时的类型信息就是通过Class对象表⽰的,这个对象包含了与类有关的信息。
其实Java中的实例对象就是通过Class对象来创建的,Java使⽤Class对象执⾏其RTTI(运⾏时类型识别,Run-Time Type Identification),多态是基于RTTI实现的。
那么在Java中哪些类型可以有Class对象呢?class:外部类、成员(成员内部类、静态内部类)、局部内部类、匿名内部类interface:接⼝[]:数组enum:枚举annotation:注解@interfaceprimitive type:基本数据类型void我们⽤代码演⽰⼀下,这些类型的Class对象都是什么?Class c1 = Object.class; // 类Class c2 = Comparable.class; // 接⼝Class c3 = String[].class; // ⼀维数组Class c4 = int[][].class; // ⼆维数组Class c5 = Override.class; // 注解Class c6 = ElementType.class; // 枚举Class c7 = Integer.class; // 基本数据类型(包装类)Class c10 = int.class; // 基本数据类型Class c8 = void.class; // 空类型Class c9 = Class.class; // ClassSystem.out.println(c1); // class ng.ObjectSystem.out.println(c2); // interface parableSystem.out.println(c3); // class [ng.String;System.out.println(c4); // class [[ISystem.out.println(c5); // interface ng.OverrideSystem.out.println(c6); // class ng.annotation.ElementTypeSystem.out.println(c7); // class ng.IntegerSystem.out.println(c10);// intSystem.out.println(c8); // voidSystem.out.println(c9); // class ng.Classint[] a = new int[10];int[] b = new int[100];/*对于数组,只要元素类型与维度⼀样,就是同⼀个Class对象*/System.out.println(a.getClass()); //class [ISystem.out.println(b.getClass()); //class [ISystem.out.println(b.getClass().hashCode()); //1735600054System.out.println(a.getClass().hashCode()); //1735600054每⼀个类都有⼀个Class对象,每当编译⼀个新类就产⽣⼀个Class对象,更准确的来说,是被保存在⼀个同名的.class⽂件中。
关于getClass(),Object.class,getClassLoader的理解

12. }
它的输出是:
uncher$AppClassLoader@2a139a55 uncher$ExtClassLoader@7852e922 null
得到了 classLoader2就是null值了。这里其实有三个类加载器:
(1): 根类加载器(null)
获得父类类对象: test.getClass().getSuperclass()
1.
2. class Father{
3. public void showName()
4. {
5. System.out.println("Father...");
6. }
7. }
8.
9. class Child extends Father{
而为什么内部类可以使用static修饰呢因为内部类算是类的成员了如果我们没有使用静态来修饰那么我们在创建内部类的时候就需要先有一个外部类的对象如果我们一直在使用内部类那么内存中就会一直存在外部类的引用而我们有时候只需要使用内部类不需要外部类那么还是会浪费内存甚至会造成内存溢出
关于 getClass(), Object.class, getClassLoader的理解
通过静态方法获取类对象,Class.forName("com.wan.Test");
在运行期间,如果我们要产生某个类的对象,Java(JVM)会检查该类型的Class对象是否已被加载。如果没有被加载,JVM会根据类的名称 找到.class文件并加载它。一旦某个类型的Class对象已被加载到内存,就可以用它来产生该类型的所有对象
(3): 应用类加载器(AppClassLoader)
它主要加载我们应用程序中的类,如Test,或者用到的第三方包,如jdbc驱动包等。
Java中的Class类

Java中的Class类Class 类是在Java语⾔中定义⼀个特定类的实现。
⼀个类的定义包含成员变量,成员⽅法,还有这个类实现的接⼝,以及这个类的⽗类。
Class类的对象⽤于表⽰当前运⾏的 Java 应⽤程序中的类和接⼝。
⽐如:每个数组均属于⼀个 Class 类对象,所有具有相同元素类型和维数的数组共享⼀个Class 对象。
基本的 Java 类型(boolean, byte, char, short,int, long, float 和 double) 和 void 类型也可表⽰为 Class 对象。
以下⽰例使⽤ Class 对象显⽰⼀个对象的 Class 名:CodeSystem.out.println("The class of " + obj + " is " + obj.getClass().getName()); }我们都知道所有的java类都是继承了object这个类,在object这个类中有⼀个⽅法:getclass().这个⽅法是⽤来取得该类已经被实例化了的对象的该类的引⽤,这个引⽤指向的是Class类的对象(呵呵,有点别扭)。
我们⾃⼰⽆法⽣成⼀个Class对象(构造函数为private),⽽这个Class类的对象是在当各类被调⼊时,由 Java 虚拟机⾃动创建 Class 对象,或通过类装载器中的 defineClass ⽅法⽣成。
我们⽣成的对象都会有个字段记录该对象所属类在CLass类的对象的所在位置。
如下图所⽰:我们可以把每个Class类的对象当做众多类的代理。
⽽且在每个Class类对象中有会有字段记录他引⽤的这个类的类加载器。
如果该字段为null,表⽰该类的加载器为bootstrap loader.具体原因见我之前分享过的⼀篇“《ClassLoader⼯作机制》”⼀⽂。
我们知道java中有多个加载器,每个加载器能载⼊多个类,所以只要取得Class类对象,就可利⽤其getClassLoader()⽅法取得该类加载器的引⽤。
java redefineclasses 原理(一)

java redefineclasses 原理(一)Java redefineclasses简介•定义:java redefineclasses是Java提供的一个用于动态修改已加载类的机制。
•功能:它允许我们在运行时重新定义一个已经存在的类,包括修改类的字段、方法以及添加新的字段和方法等操作。
实现原理1.定义Class文件:Java程序首先要对被修改的类进行重新编译,生成新的Class文件。
2.设置Class文件存储路径:通过设置系统属性“”来指定新生成的Class文件的存储路径。
3.加载新Class文件:利用自定义的ClassLoader加载新生成的Class文件,以加载新的定义。
4.使用Instrumentation API:通过Instrumentation API向JVM注入新修改的Class定义,替换原有的定义。
5.修改完成:类重新加载后,就可以使用新的定义。
•代码热替换:使用redefineclasses可以在不重启应用的情况下,动态修改已加载类的代码,实现代码的热替换,提高开发效率。
•应用插件系统:通过动态修改已加载类,可以加载和卸载应用插件,从而实现插件式开发,增加系统的可扩展性。
代码示例import ;public class MyClass {public static void premain(String agentArgs, Instrum entation inst) {(new MyTransformer());}}public class MyTransformer implements ClassFileTransform er {public byte[] transform(ClassLoader loader, String c lassName, Class<?> classBeingRedefined,ProtectionDomain protectionDomain, byte[] cl assfileBuffer) throws IllegalClassFormatException {// 修改classfileBuffer中的字节码// 返回修改后的字节码}注意事项•redefineclasses的操作需要在Java虚拟机启动前进行,可以通过添加启动参数”-javaagent:“来指定自定义的Agent。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
Java中Class类工作原理详解1.Class对象Class对象包含了与类相关的信息。
事实上,Class对象就是用来创建类的所有的"普通"对象的。
类是程序的一部分,每个类都有一个Class对象。
换言之,每当编写并且编译了一个新类,就会产生一个Class对象(恰当地说,是被保存在一个同名的。
class文件中)。
在运行时,当我们想生成这个类的对象时,运行这个程序的Java虚拟机(JVM)首先检查这个类的Class 对象是否已经加载。
如果尚未加载,JVM就会根据类名查找。
class文件,并将其载入。
一旦某个类的Class对象被载入内存,它就被用来创建这个类的所有对象。
看下面示例。
SweetShop.javapackage com.zj.sample;class Candy {static {System.out.println("Loading Candy");}}class Gum {static {System.out.println("Loading Gum");}}class Cookie {static {System.out.println("Loading Cookie");}}public class SweetShop {public static void main(String[] args) {System.out.println("inside main");new Candy();System.out.println("After creating Candy");try {Class.forName("com.zj.sample.Gum");} catch (ClassNotFoundException e) {System.out.println("Couldn't find Gum");}System.out.println("After Class.forName("Gum")"); new Cookie();System.out.println("After creating Cookie");}}结果:inside mainLoading CandyAfter creating CandyLoading GumAfter Class.forName("Gum")Loading CookieAfter creating Cookie2.获取Class实例的三种方式1)利用对象调用getClass()方法获取该对象的Class实例。
2)使用Class类的静态方法forName(),用类的名字获取一个Class实例。
3)运用。
class的方式来获取Class实例,对于基本数据类型的封装类,还可以采用。
TYPE 来获取相对应的基本数据类型的Class实例。
3.Class.forName上面的示例中:Class.forName("com.zj.sample.Gum");这个方法是Class类(所有Class对象都属于这个类)的一个static成员。
Class对象就和其它对象一样,我们可以获取并操作它的引用。
forName()是取得Class对象的引用的一种方法。
它是用一个包含目标类的文本名的String作输入参数,返回的是一个Class对象的引用。
4.类字面常量Java还提供了另一种方法来生成对Class对象的引用,即使用"类字面常量"。
对上述程序来说,可以是:com.zj.sample.Gum.class;5.关键字instanceof关键字instanceof返回一个布尔值,判断是不是某个特定类型的实例。
if(x instanceof Dog) ((Dog)x)。
bark();6.获取Class实例package com.zj.sample;class Point {int x, y;}class ClassTest {public static void main(String[] args) {Point pt = new Point();Class c1 = pt.getClass();System.out.println(c1.getName());try {Class c2 = Class.forName("com.zj.sample.Point"); System.out.println(c2.getName());} catch (Exception e) {e.printStackTrace();}Class c3 = Point.class;System.out.println(c3.getName());Class c4 = int.class;System.out.println(c4.getName());Class c5 = Integer.TYPE;System.out.println(c5.getName());Class c6 = Integer.class;System.out.println(c6.getName());}}结果:com.zj.sample.Pointcom.zj.sample.Pointcom.zj.sample.Pointintintng.Integer7.Class的其他方法1)Class.newInstance()使用所选的Class对象生成该类的新实例。
它调用了缺省(无参数)的类构造器生成新的对象。
所以使用newInstance()创建的类必须有一个缺省构造器。
对于newInstance()来说,可以在原先没有任何对象存在的情况下,使用它创建一个新的对象。
利用newInstance()实例化一个对象:package com.zj.sample;class Point {static {System.out.println("Loading Point");}int x, y;}class ClassTest {public static void main(String[] args) {try {Class c = Class.forName("com.zj.sample.Point");Point pt = (Point) c.newInstance();} catch (Exception e) {e.printStackTrace();}}}结果:Loading Point2)Class.isInstance()方法提供了一种动态地调用instanceof运算符的途径。
3)Class.getInterfaces()方法返回Class对象的数组,这些对象代表的是某个Class对象所包含的接口。
4)如果有一个Class对象,那么就可以通过getSuperclass()获取它的直接基类。
这个方法自然也是返回一个Class引用,所以可以进一步查询其基类。
这意味着在运行时,可以找到一个对象完整的类层次结构。
5)Class类支持反射的概念,Java附带的库ng.reflect包含了Field、Method以及Constructor类(每个类都实现了Member接口)。
这些类型的对象是由JVM在运行时创建的,用以表示未知类里对应的成员。
这样可以使用Constructor创建新的对象,用get()和set()方法读取和修改与Field对象关联的字段,用invoke()方法调用与Method对象关联的方法。
另外,还可以调用getFields()、getMethods、getConstrucotrs()方法,返回表示字段、方法以及构造器的对象的数组。
8.利用反射API察看未知类的构造方法与方法package com.zj.sample;import ng.reflect.Constructor;import ng.reflect.Method;class Point {static {System.out.println("Loading Point");}int x, y;void output() {System.out.println("x=" + x + "," + "y=" + y);}Point(int x, int y) {this.x = x;this.y = y;}}class ClassTest {public static void main(String[] args) {try {Class c = Class.forName("com.zj.sample.Point");Constructor[] cons = c.getDeclaredConstructors();for (int i = 0; i < cons.length; i++)// 返回所有声明的构造方法{System.out.println(cons[i]);}Method[] ms = c.getDeclaredMethods();for (int i = 0; i < ms.length; i++)// 返回所有声明的方法{System.out.println(ms[i]);}} catch (Exception e) {e.printStackTrace();}}}结果:Loading Pointcom.zj.sample.Point(int,int)void com.zj.sample.Point.output()9.动态调用一个类的实例(完全没有出现point这个名字) package com.zj.sample;import ng.reflect.Constructor;import ng.reflect.Method;class Point {static {System.out.println("Loading Point");}int x, y;void output() {System.out.println("x=" + x + "," + "y=" + y);}Point(int x, int y) {this.x = x;this.y = y;}}class ClassTest {public static void main(String[] args) {try {Class c = Class.forName("com.zj.sample.Point");Constructor[] cons = c.getDeclaredConstructors();Class[] params = cons[0].getParameterTypes();// 察看构造器的参数信息Object[] paramValues = new Object[params.length];// 构建数组传递参数for (int i = 0; i < params.length; i++) {if (params[i].isPrimitive())// 判断class对象表示是否是基本数据类型{paramValues[i] = new Integer(i);}}Object o = cons[0].newInstance(paramValues);// 创建一个对象的实例Method[] ms = c.getDeclaredMethods();// 调用方法ms[0].invoke(o, null);// 用指定的参数调用(output方法没有参数,null) } catch (Exception e) {e.printStackTrace();}}}结果:Loading Pointx=0,y=1。