关于java-Class类的简单分析
java有个Class的基类,高级编程的时候,务必要理解这个。
粗略看下,可以明白了解Class这个类对于了解和掌握java非常重要。
Class这个类的包路径是:java.lang.Class<T>
可以看出来这是一个非常基础,非常核心的类,因为它的包路径位于java.lang,即java的语言包下面,可谓核心的核心。
一、开个好头
a.先看引入部分
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Array;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.GenericDeclaration;
import java.lang.reflect.Member;
import java.lang.reflect.Field;
import java.lang.reflect.Executable;
import java.lang.reflect.Method;
import java.lang.reflect.Constructor;
import java.lang.reflect.Modifier;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.AnnotatedType;
import java.lang.ref.SoftReference;
import java.io.InputStream;
import java.io.ObjectStreamField;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Set;
import java.util.Map;
import java.util.HashMap;
import java.util.Objects;
import sun.misc.Unsafe;
import sun.reflect.CallerSensitive;
import sun.reflect.ConstantPool;
import sun.reflect.Reflection;
import sun.reflect.ReflectionFactory;
import sun.reflect.generics.factory.CoreReflectionFactory;
import sun.reflect.generics.factory.GenericsFactory;
import sun.reflect.generics.repository.ClassRepository;
import sun.reflect.generics.repository.MethodRepository;
import sun.reflect.generics.repository.ConstructorRepository;
import sun.reflect.generics.scope.ClassScope;
import sun.security.util.SecurityConstants;
import java.lang.annotation.Annotation;
import java.lang.reflect.Proxy;
import sun.reflect.annotation.*;
import sun.reflect.misc.ReflectUtil;
为了简化,我们把sun.refect.annotation.*算作一个,共有import语句45个,其中:27个和reflect(反射)有关,10个和java.util明显有关,3个和security(安全)有关,2个和io有关,余者3个。
所以这个Class类,可以大体理解为和反射,工具,安全,io有关的工具类。依赖那么多反射是因为必须通过反射来解析目标类或者对象。
如果可以,也大体可以这么认为:Class类大体就是通过反射功能分析和处理类的工具类。虽然它不仅仅是这样。
b.看下这个类的头部注释
头部的注释可谓是本类意图的较好表达。
为了便于大家查看,这里只列出JavaDoc显示的结果:
java.lang.Class<T> Instances of the class Class represent classes and interfaces in a running Java application. An enum is a kind ofclass and an annotation is a kind of interface.
Every array also belongs to a class that is reflected as a Class objectthat is shared by all arrays with the same element type and number of dimensions.
The primitive Java types (boolean, byte, char, short, int, long, float, and double), and the keyword void are also represented as Class objects.
Class has no public constructor. Instead Classobjects are constructed automatically by the Java Virtual Machine as classesare loaded and by calls to the defineClass method in the classloader. The following example uses a Class object to print theclass name of an object: void printClassName(Object obj) {
System.out.println("The class of " + obj +
" is " + obj.getClass().getName());
} It is also possible to get the Class object for a namedtype (or for void) using a class literal. See Section 15.8.2 of The Java Language Specification.For example:
System.out.println("The name of class Foo is: "+Foo.class.getName());
Type Parameters:<T> the type of the class modeled by this Classobject. For example, the type of String.class is Class<String>.
Use Class<?> if the class being modeled isunknown.
Since:JDK1.0
Author:unascribed
See Also:java.lang.ClassLoader.defineClass(byte [], int, int)
当然,也不仅仅是这个注释重要,整个类文件有3639行(rt.jar中,版本1.8.0_301),还有许多的属性和方法都具有较长的注释。
后面的注释后面说,开头这里先说说这一段话什么意思:
原文:
Instances of the class Class represent classes and interfaces in a running Java application. An enum is a kind of class and an annotation is a kind of interface.
Every array also belongs to a class that is reflected as a Class object that is shared by all arrays with the same element type and number of dimensions.
The primitive Java types (boolean, byte, char, short, int, long, float, and double), and the keyword void are also represented as Class objects.
Class has no public constructor. Instead Class objects are constructed automatically by the Java Virtual Machine as classes are loaded and by calls to the defineClass method in the classloader.
译文:
类Class的实例描绘了正在jvm中运行的类的接口。一个enum(枚举)是一种类,一个annotation(注解)是一种接口。
每个array也归属于一个类,这个类表示一个Class对象,这个对象被具有同个元素类型和维度的所有数组共享。
原始的java类型(boolean,byte,char,short,int,long,float和double),以及关键字void也被表示为一个Class对象。
Class没有公共的构造函数。但是Class对象可以被jvm自动构造,具体的方式是当类被加载,并由classloader执行defineClass方法。
c.历史
看一个图片:
注:
a.以上统计仅仅基于@since关键字,但还有许多方法是没有@since的,这些就是1.0就提供的。since1.0是放在Class定义头之上。
b.原来since后面跟的不都是 数字,例如1.0,1.8,而是有的 以JDK开头,有的直接就是一个数字。 从1.2(包含1.2)之后就不再带有JDK字眼,而是形如 @since 1.5
有意思吧,这个统计充分表明了几个信息:
1.从1.0开始java就构思这个基类,这个@since JDK1.0是放在类头,原文“ * @since JDK1.0”
2.版本 1.1,1.5,1.8引入了最多的,大体占据了89%
针对每个版本引入的新特性,对照每个发行申明中的新特性,就可以发现二者之间的紧密关系,而这种关联是想当然的。
二、定义
a. 定义
public final class Class<T> implements java.io.Serializable,
GenericDeclaration,
Type,
AnnotatedElement
关键点:泛型、可序列化、通用定义、类型、注解
说明Class可以处理各种类的定义,类型和注解。
b.罕见关键字列表
这个罕见,是说在一般的应用编程中。
先理解这个词语,方能继续分析。
- primitive -- 发音 英 [ˈprɪmətɪv] 。含义:原始,本类用于表达一个类型是否原始类型
- volatile --
- 发音和原意思见百度翻译-200种语言互译、沟通全世界! (baidu.com),大意是五常性
- 具体用法见 (37条消息) Java volatile关键字最全总结:原理剖析与实例讲解(简单易懂)_老鼠只爱大米的博客-CSDN博客_java volatile
- 小结:java用这个修饰变量或者方法,目的是为了在多线程下共享变量或者方法块
- transient
- 发音和原来意思见 https://fanyi.baidu.com/?aldtype=85#en/zh/transient,大概意思是 转瞬即逝
- 具体用法见 java transient初探 - 袁立 - 博客园 (cnblogs.com)
- 小结: 这个是用于修饰对象属性,主要是控制是否序列化,这个容易让人想起JackSon或者fastJson的JsonIgnore
- native
- 发音和含义见 百度翻译-200种语言互译、沟通全世界! (baidu.com) ,大意是出生地的。
- 具体用法见 java中native的用法 - 不止吧 - 博客园 (cnblogs.com)
- 小结:主要修饰非java api方法
- SYNTHETIC
- 发音:[sɪnˈθetɪk] 。含义:合成的(形容词);合成物(名词)
- 具体用法:
- Java synthetic - -CoderLi - 博客园 (cnblogs.com)
- Synthetic Class in Java - Stack Overflow Java has the ability to create classes at runtime. These classes are known as Synthetic Classes or Dynamic Proxies
http://www.javaworld.com/article/2073578/java-s-synthetic-methods.html
http://javapapers.com/core-java/java-synthetic-class-method-field/
- http://java.sun.com/j2se/1.5.0/docs/guide/reflection/proxy.html
- 小结:这个东西常见于编译后的修饰说明,一般我们不会在代码中使用这个关键字。这是编译器编译java文件后的class文件中的关键字。所以这个词语理解为编译器合成/动态合成,也许更加贴切一些。
- 但也不仅仅是这样,还可能是动态代理的时候使用。
- Package
- 含义:包,即java中的包
- @CallerSensitive
- 含义:主调者敏感,大意是根据不同的主调者而有所不同
- 具体定义见 @CallerSensitive一些理解 - 追求极致 - 博客园 (cnblogs.com)
- 小结:大体可以理解为是一种安全机制,保证安全调用。
- ConstantPool
- 含义:常量池,是太阳公司反射包中一个类,用于获取jvm常量有关信息
三、构成
内容太多,没有必要一一罗列,只列出自己关注的部分。
函数和方法
- forName
- newInstance
- getGenericSuperclass
- getDeclaredFields
- getDeclaredMethods
- getResource
- getAnnotations
- getAnnotatedInterfaces
四、主要功能
- 获取类或者接口信息
- 反射,一遍动态编程
五、Object和getClass
为了配合反射,java的祖类Object,增加了一些重要的内容:
public final native Class<?> getClass();
这是一个泛型的native方法,且是final,即由jvm native块执行。
该方法的注释:
* @return The {@code Class} object that represents the runtime
* class of this object.
有了这个方法,反射就变得很容易了。
除了通过getClass获取Class,也可以直接在类名后跟上class获取,例如:
Class<ChineseMan> cc= ChineseMan.class;
直接看Object本身的定义并没有这个属性,但确可以使用,这是因为编译器自动做了这个活。
六、JVM
Class类的大量功能和内容和JVM是绑定在一起的。 贴几个JVM结构图:(注下图直接bing获取的,没有注意来源)
再来一个更加清楚的:
关于jvm,非长篇大论不足以详知,非本文内容,有关内容自行搜索,或者查看以下内容:
本文列出jvm内容,是为了说明native这个东西。native是jvm活着的主要目的,当然jvm不仅仅是native还有Excecution Engine(执行引擎)。因为这个,java其实够慢的。
七、示例
package study.base.reflect; import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.ArrayList;
import java.util.List; import org.apache.commons.lang.StringUtils; import study.base.classes.ChineseMan; public class ReflectTest { public static void printClassTree(Class<?> c) {
List<String> classNameList=new ArrayList<String>();
getClassTree(c,classNameList); int lvl=classNameList.size();
for(int i=lvl-1;i>=0;i--) {
int paddingQty=lvl-i;
String paddingString=StringUtils.leftPad("", paddingQty,"-");
System.out.println(paddingString+classNameList.get(i));
} } public static void getClassTree(Class<?> c,List<String> result){
result.add(c.getName());
if (c.getSuperclass()!=null) {
getClassTree(c.getSuperclass(),result);
}
} public static void printMethod(Method[] methods) {
if (methods.length==0) {
System.out.println("没有任何方法!");
}
for (Method item:methods) {
System.out.println(item.getDeclaringClass().getName()+":"+item.getName());
Parameter[] params=item.getParameters();
if (params.length>0) {
for(Parameter p:params) {
System.out.println(
" "+p.getParameterizedType().getTypeName()+" "+p.getName()
);
}
}
}
} public static void printFileds(Field[] fields) {
for(Field item:fields) {
System.out.println(item.getName()+":"+item.getType().isPrimitive());
}
} @SuppressWarnings({ "rawtypes", "unchecked" })
public static void main(String[] args) {
ChineseMan cm=new ChineseMan("lzf");
cm.setLeftPadding(" --");
Class<ChineseMan> cc=ChineseMan.class;
printClassTree(cc);
System.out.println("-------------------------------------------------------");
System.out.println("获取类ChineseMan特有方法");
Method[] methods=cc.getDeclaredMethods();
printMethod(methods); System.out.println("-------------------------------------------------------");
System.out.println("获取类ChineseMan的所有属性");
printFileds(cc.getDeclaredFields()); System.out.println("-------------------------------------------------------");
System.out.println("执行cm的当前类方法--具有返回结果");
Class voidClass=Void.class;
String voidClassName=voidClass.getSimpleName().toLowerCase();
for (Method item:methods) {
Class returnType=item.getReturnType();
String returnTypeClassName=returnType.getSimpleName().toLowerCase();
if (!returnTypeClassName.equals(voidClassName)) {
try {
Object result=item.invoke(cm);
System.out.println(item.getName()+":"+result.toString());
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
} System.out.println("-------------------------------------------------------");
System.out.println("获取ChineseMan所有方法(含祖先)");
methods=cc.getMethods();
printMethod(methods); System.out.println("-------------------------------------------------------");
System.out.println("执行ChineseMan的父亲类"+cc.getSuperclass().getName()+"方法");
System.out.println("-------------------------------------------------------");
methods=cc.getSuperclass().getDeclaredMethods();
for (Method item:methods) {
//System.out.println(item.getName());
if (item.getParameters().length==0) {
try {
System.out.print(" "+item.getName()+":");
if (!item.getReturnType().getSimpleName().toLowerCase().equals(voidClassName)) {
Object result=item.invoke(cm);
System.out.println(result.toString());
}
else {
item.invoke(cm);
} } catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
else {
System.out.println(" "+item.getName()+"(...)");
} }
} }
直接结果如下:
-java.lang.Object
--study.base.classes.Organisms
---study.base.classes.Animal
----study.base.classes.Human
-----study.base.classes.Man
------study.base.classes.ChineseMan
-------------------------------------------------------
获取类ChineseMan特有方法
study.base.classes.ChineseMan:set斗志
java.lang.String 斗志
study.base.classes.ChineseMan:get斗志
study.base.classes.ChineseMan:set力量
java.lang.String 力量
study.base.classes.ChineseMan:get力量
study.base.classes.ChineseMan:setSoldier
boolean isSoldier
study.base.classes.ChineseMan:isSoldier
study.base.classes.ChineseMan:toString
-------------------------------------------------------
获取类ChineseMan的所有属性
isSoldier:true
斗志:false
力量:false
-------------------------------------------------------
执行cm的当前类方法--具有返回结果
get斗志:100
get力量:100
isSoldier:true
toString:ChineseMan{
姓名:lzf,
力量:100,
斗志:100
}
-------------------------------------------------------
获取ChineseMan所有方法(含祖先)
study.base.classes.ChineseMan:set斗志
java.lang.String 斗志
study.base.classes.ChineseMan:get斗志
study.base.classes.ChineseMan:set力量
java.lang.String 力量
study.base.classes.ChineseMan:get力量
study.base.classes.ChineseMan:setSoldier
boolean isSoldier
study.base.classes.ChineseMan:isSoldier
study.base.classes.ChineseMan:toString
study.base.classes.Man:born
study.base.classes.Man:work
study.base.classes.Man:eat
study.base.classes.Man:getLeftPadding
study.base.classes.Man:familywork
study.base.classes.Man:growOld
study.base.classes.Man:disappear
study.base.classes.Man:fallSick
study.base.classes.Man:fight
study.base.classes.Man:die
study.base.classes.Man:bear
study.base.classes.Man:teach
study.base.classes.Man:setLeftPadding
java.lang.String leftPadding
study.base.classes.Man:run
study.base.classes.Human:setGender
java.lang.String gender
study.base.classes.Human:getGender
study.base.classes.Human:sleep
study.base.classes.Animal:getEatable
study.base.classes.Animal:setEatable
java.lang.Boolean eatable
study.base.classes.Organisms:setLocation
java.lang.String location
study.base.classes.Organisms:setType
java.lang.String type
study.base.classes.Organisms:getName
study.base.classes.Organisms:getLocation
study.base.classes.Organisms:setName
java.lang.String name
study.base.classes.Organisms:getType
java.lang.Object:wait
java.lang.Object:wait
long arg0
int arg1
java.lang.Object:wait
long arg0
java.lang.Object:equals
java.lang.Object arg0
java.lang.Object:hashCode
java.lang.Object:getClass
java.lang.Object:notify
java.lang.Object:notifyAll
-------------------------------------------------------
执行ChineseMan的父亲类study.base.classes.Man方法
-------------------------------------------------------
born: --生当作人杰,死亦为鬼雄!
work: --锄禾日当午,汗滴禾下土!
以天为盖,以地为舆
eat: --但使残年饱吃饭,只愿无事常相见
getLeftPadding: --
familywork: --子不教,父之过!
growOld: --儿童相见不相识,笑问客从何处来!
disappear: --神龟虽寿,犹有竞时;腾蛇乘雾,终成土灰
fallSick: --僵卧孤村不自哀,尚思为国戍轮台
fight: --黄沙百战穿金甲,不破楼兰终不还
die: --人生自古谁无死,留取丹心照汗青
bear: --男人不能生孩子
teach: --师者,所以传道授业解惑者也!
setLeftPadding(...)
run: --醉里挑灯看剑,梦回吹角连营!
八、参考资料
参考内容太多,不一一列出,有的已经在前文列出。
Java发行历史(截止1.8) https://blog.csdn.net/wq6ylg08/article/details/91351603
关于java-Class类的简单分析的更多相关文章
- rocketmq中的NettyRemotingClient类的简单分析
rocketmq中的NettyRemotingClient类的简单分析 Bootstrap handler = this.bootstrap.group(this.eventLoopGroupWork ...
- java基础---->hashSet的简单分析(一)
对于HashSet而言,它是基于HashMap实现的,底层采用HashMap来保存元素的.今天我们就简单的分析一下它的实现.人生,总会有不期而遇的温暖,和生生不息的希望. HashSet的简单分析 一 ...
- Java简单实验--关于课后提到的java重载函数的简单分析
根据这一小段代码,获得了以下的测试截图: 简单分析:根据输出结果,判断这段代码用到了两个不同的函数方法,输出的不止有double类型的数,还有整型的数. 又根据类中的定义情况,square是根据判断传 ...
- Java File类的简单使用
Java File的简单使用(创建.删除.遍历.判断是否存在等) Java文件类以抽象的方式代表文件名和目录路径名.该类本身不能用来读数据或写数据,它主要用于磁盘上文件和目录的创建.文件的查找和文件的 ...
- Java自定义异常类的简单实现
学习目标: 掌握自定义异常类 例题: 需求:自定义异常类,简单判断是否注册成功 代码如下: RegisterException类: /** * @author YanYang * @projectNa ...
- Java程序内存的简单分析
这篇文章将简单的说明下当我们运行Java程序时JVM(Java虚拟机)的内存分配情况. 首先我们先来感观的认识下几个名词: 1.栈,一般来说,基本数据类型直接在栈中分配空间,局部变量(在方法代码段中定 ...
- Java Properties类源码分析
一.Properties类介绍 java.util.Properties继承自java.util.Hashtable,从jdk1.1版本开始,Properties的实现基本上就没有什么大的变动.从ht ...
- Java内存模型JMM简单分析
参考博文:http://blog.csdn.net/suifeng3051/article/details/52611310 http://www.cnblogs.com/nexiyi/p/java_ ...
- java.lang.IllegalStateException异常简单分析和简单解决
我们在做文件上传或者下载,或者过滤等操作时,可能要用到页面的输出流. 例如在JSP使用: response.reset(); response.setContentType(”application/ ...
- Tomcat容器运行struts2+spring+mybatis架构的java web应用程序简单分析
1.具体的环境为 MyEclipse 8.5以及自带的tomcat spring3.0.5 struts2.3.15.1 mybatis3.0.5 2.想弄明白的一些问题 tomcat集成spring ...
随机推荐
- dotnet 6 推荐一个可代替 .NET Remoting 的 IPC 库
本文将来和大家推荐一个基于最友好 MIT 协议的完全在 GitHub 上开源的,可代替 .NET Remoting 的 IPC 本机多进程通讯库 本机内多进程通讯 IPC 不同于跨设备系统的 RPC ...
- dotnet C# 只创建对象不调用构造函数方法
有时我期望只是创建出对象,但是不要调用对象的构造方法,可以通过使用 FormatterServices 的 GetUninitializedObject 函数来实现只创建对象不调用构造函数方法 这个 ...
- SQL server 批量删除表
select 'drop table '+name+';' from sys.tables declare c cursor forselect NAME from sysobjects where ...
- github只下载某个文件或文件夹(使用GitZip插件)
安装GitZip插件 (此安装过程需要梯子(不懂"梯子",百度一下就明白)) 1. 打开插件管理页面 方法一:打开Chrome浏览器(Edge浏览器同理),在Chrom地址栏输入c ...
- 生成带重复的笛卡尔乘积过程 Cartesian Product with Repetition
目录 What is Cartesian Product with Repetition Code Demo What is Cartesian Product with Repetition 比如说 ...
- 八、Doris外部表及数据导入
DorisDB提供了多种导入方式,用户可以根据数据量大小.导入频率等要求选择最适合自己业务需求的导入方式. 数据导入: 1.离线数据导入:如果数据源是Hive/HDFS,推荐采用 Broker Lo ...
- .Net 8.0 下的新RPC,IceRPC之如何创建连接connection
作者引言 很高兴啊,我们来到了IceRPC之如何创建连接connection,基础引导,让自已不在迷茫,快乐的畅游世界. 如何创建连接connection 学习如何使用IceRPC,创建和接受连接. ...
- sendmail发送慢的问题
1.使用python的脚本,发送邮件.代码如下: 点击查看代码 [root@ZabbixServerMasterNode ~]# cd /etc/zabbix/alertscripts/ [root@ ...
- fork后更新仓库代码
目录 fork后更新仓库代码 场景: 模型 操作方法如下: 方法一.从github上进行操作然后更新 如何在 Github 网页端同步更新? 方法二.通过命令行fetch拉取原仓库更新 fork后更新 ...
- vue路由跳转的三种方式
目录 1.router-link [实现跳转最简单的方法] 2.this.$router.push({ path:'/user'}) 3.this.$router.replace{path:'/' } ...