java getclassloader_关于getClass(),Object.class,getClassLoader的理解

java getclassloader_关于getClass(),Object.class,getClassLoader的理解1、对Class类的理解:Class类包含了类的信息,如构造方法、方法、属性,可用于反射。以下是所有方法2、获取Class类对象的几种方法:Testtest=newTest();(1).test.getClass();在运行时确定,所以运行实例才是该类对象。super.getClass()不能获得父类的类对象,仍然是当前类对象。获得父类类对象:test.getClass().getSup…

大家好,又见面了,我是你们的朋友全栈君。

1、对Class类的理解:Class类包含了类的信息,如构造方法、方法、属性,可用于反射。以下是所有方法

26974e6773ba4bbf228f413ba6b6bf75.png2、获取Class类对象的几种方法:

Test test = new Test();

(1).test.getClass();

在运行时确定,所以运行实例才是该类对象。super.getClass()不能获得父类的类对象,仍然是当前类对象。

获得父类类对象: test.getClass().getSuperclass()

class Father{

public void showName()

{

System.out.println(“Father…”);

}

}

class Child extends Father{

public void showName()

{

System.out.println(“children”);

}

}

Father father = new Child();

System.out.println(Father.class); 结果是 Father

System.out.println(father.getClass()); 结果是 Child

(2).Test.class;

在编译时确定,返回当前类的类对象实例。不会加载静态变量

获得父类类对象: Test.class.getSuperclass()

(3).Class.forName(“类路径”);会加载静态变量,比如jdbc驱动利用这个加载一些静态属性

通过静态方法获取类对象,Class.forName(“com.wan.Test”);

在运行期间,如果我们要产生某个类的对象,Java虚拟机(JVM)会检查该类型的Class对象是否已被加载。如果没有被加载,JVM会根据类的名称找到.class文件并加载它。一旦某个类型的Class对象已被加载到内存,就可以用它来产生该类型的所有对象

普通类为什么不能用static修饰?

讲一下个人理解吧。static修饰的东西被我们成为类成员,它会随着类的加载而加载,比如静态代码块,静态成员,静态方法(这里只是加载,并没有调用)等等,可以假象一下,如果把一个Class文件中的外部类设为static,那目的何在呢?难道让这个类随着应用的启动而加载吗?如果我在这次使用过程中根本没有使用过这个类,那么是不是就会浪费内存。这样来说设计不合理,总而言之,设计不合理的地方,Java是不会让它存在的。

而为什么内部类可以使用static修饰呢,因为内部类算是类的成员了,如果我们没有使用静态来修饰,那么我们在创建内部类的时候就需要先有一个外部类的对象,如果我们一直在使用内部类,那么内存中就会一直存在外部类的引用,而我们有时候只需要使用内部类,不需要外部类,那么还是会浪费内存,甚至会造成内存溢出。使用static修饰内部类之后,内部类在创建对象时就不需要有外部类对象的引用了。

最终结论就是:static可以用来修饰内部类,但是不可以用来修饰外部类

3、classLoader相关理解

请在Eclipse中新建如下类,并运行它:

package java.lang;

public class Long {

public static void main(String[] args) {

System.out.println(“Hi, i am here”);

}

}

你能猜到它的运行如果吗? 不错,就是如下这个样子!

错误: 在类 java.lang.Long 中找不到 main 方法, 请将 main 方法定义为:

public static void main(String[] args)

否则 JavaFX 应用程序类必须扩展javafx.application.Application

为什么呢,明明我在Long方法类中定义了main方法,为什么说main方法没有定义呢?

本文将解决以上问题出现的原因。

二、ClassLoader的作用

我们都知道java程序写好以后是以.java(文本文件)的文件存在磁盘上,然后,我们通过(bin/javac.exe)编译命令把.java文件编译成.class文件(字节码文件),并存在磁盘上。但是程序要运行,首先一定要把.class文件加载到JVM内存中才能使用的,我们所讲的classLoader,就是负责把磁盘上的.class文件加载到JVM内存中,如下图所示:

6867a86b3c3cb45cd37db4752fda012c.png

你可以认为每一个Class对象拥有磁盘上的那个.class字节码内容,每一个class对象都有一个getClassLoader()方法,得到是谁把我从.class文件加载到内存中变成Class对象的。

三、ClassLoader层次结构

请执行如下程序:

48304ba5e6f9fe08f3fa1abda7d326ab.png

public class Test {

public static void main(String[] args) {

ClassLoader classLoader = Test.class.getClassLoader();

System.out.println(classLoader);

ClassLoader classLoader1 = classLoader.getParent();

System.out.println(classLoader1);

ClassLoader classLoader2 = classLoader1.getParent();

System.out.println(classLoader2);

}

}

48304ba5e6f9fe08f3fa1abda7d326ab.png

它的输出是:

sun.misc.Launcher$AppClassLoader@2a139a55

sun.misc.Launcher$ExtClassLoader@7852e922

null

得到了 classLoader2就是null值了。这里其实有三个类加载器:

(1): 根类加载器(null)

它是由本地代码(c/c++)实现的,你根本拿不到他的引用,但是他实际存在,并且加载一些重要的类,它加载(%JAVA_HOME%\jre\lib),如rt.jar(runtime)、i18n.jar等,这些是Java的核心类。

(2): 扩展类加载器(ExtClassLoader)

虽说能拿到,但是我们在实践中很少用到它,它主要加载扩展目录下的jar包, %JAVA_HOME%\lib\ext

(3): 应用类加载器(AppClassLoader)

它主要加载我们应用程序中的类,如Test,或者用到的第三方包,如jdbc驱动包等。

这里的父类加载器与类中继承概念要区分,它们在class定义上是没有父子关系的。

四、Class加载时调用类加载器的顺序

当一个类要被加载时,有一个启动类加载器和实际类加载器的概念,这个概念请看如下分析

如上面的Test.class要进行加载时,它将会启动应用类加载器进行加载Test类,但是这个应用类加载器不会真正去加载他,而是会调用看是否有父加载器,结果有,是扩展类加载器,扩展类加载器也不会直接去加载,它看自己是否有父加载器没,结果它还是有的,是根类加载器。

所以这个时候根类加载器就去加载这个类,可在%JAVA_HOME%\jre\lib下,它找不到com.Test这个类,所以他告诉他的子类加载器,我找不到,你去加载吧,子类扩展类加载器去%JAVA_HOME%\lib\ext去找,也找不着,它告诉它的子类加载器 AppClassLoader,我找不到这个类,你去加载吧,结果AppClassLoader找到了,就加到内存中,并生成Class对象。

这个时间时候启动类加载器(应用类加载器)和实际类加载器(应用类加载器)是同一个.

这就是Java中著名的委托加载机制,看如下图:

d8acc34b21341d35ab24a4dc40c18e37.png

我们再来看一下 java.lang.Long的加载,按上面分析,应该是由根类加载器加载得到的,此时启动类加载器是应用类加载器,但实际类加载器是根类加载器。

所以回到我们最开始那个问题,没有main方法是因为执行的根本不是我们自己写的类,执行的是java核心中的那个Long类,当然没有main方法了。 这样就防止我们应用中写的类覆盖掉java核心类。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/132176.html原文链接:https://javaforall.net

赞 (0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 眼下最好的JSP分页技术

    眼下最好的JSP分页技术

    2021年11月23日
  • p90灯珠和p70灯珠区别_pc50是什么材料

    p90灯珠和p70灯珠区别_pc50是什么材料p50,p90,p99(或者写作pct50,pct90,pct99)都是数据聚合统计一种方式,跟百分比相关。p50:数据集按升序排列,第50分位置大的数据(即升序排列后排在50%位置的数据)。p90:数据集按升序排列,第90分位置大的数据(即升序排列后排在90%位置的数据)。p99:数据集按升序排列,第99分位置大的数据(即升序排列后排在99%位置的数据)。有什么实际含义和用处?经常用来衡量服务响应延迟。以最常用的p99为例,它衡量了99%的情况下能达到的最大延迟,99%的请求都低于

    2022年10月31日
  • kali更新源(软件更新,附kali源列表)

    kali更新源(软件更新,附kali源列表)kali更新源(软件更新)源列表见文末(2019年10月5日更新)1.vim/etc/apt/sources.list文件添加如图内容,保存退出即可。2.刷新软件包列表apt-getupdate注:VMwareWorkstation中的虚拟机需要调成桥接或者NAT模式,保证虚拟机可以上网。…

    2022年5月8日
  • 什么是robots.txt文件

    什么是robots.txt文件一、什么是robots文件Robots.txt文件是网站跟爬虫间的协议,对于专业SEO并不陌生,用简单直接的txt格式文本方式告诉对应的爬虫被允许的权限,也就是说robots.txt是搜索引擎中访问网站的时候要查看的第一个文件。当一个搜索蜘蛛访问一个站点时,它会首先检查该站点根目录下是否存在robots.txt,如果存在,搜索机器人就会按照该文件中的内容来确定访问的范围;如果该文件不存在,所有的搜索蜘蛛将能够访问网站上所有没有被口令保护的页面。如您的网站未设置robots协议,搜索引擎对网.

    2022年5月23日
  • linux卸载默认java_趋势卸载默认密码

    linux卸载默认java_趋势卸载默认密码在Linux下有的时候需要重新配置jdk,因为环境变量是使用默认安装的jdk,这个默认安装的jdk不卸载掉,那么新配置的环境变量将不会生效,所以常见到的问题就是,明明配置了环境变量/etc/profile,但是java-version却不生效,就是这个原因!以下是相关卸载和配置:一、查看Jdk的安装路径:$whereisjava$whichjava(java执行路径)…

    2022年10月1日
  • 【python】Windows中编译安装libsamplerate和scikits.samplerate

    【python】Windows中编译安装libsamplerate和scikits.sampleratelibrosa缘由librosa是一个音频和音乐处理的Python包,我用它来做音频的特征提取。但是在使用时,发现librosa.load将音乐文件转化为时间序列的过程中,速度实在难以忍受,cpu跑的非常高,程序好像假死的状态。查阅官方文档发现,默认情况下,librosa会使用scipy.signal进行音频信号的重采样,这在实际使用时是很慢的。如果要获得很高的性能,官方建议安装libsampl

    2022年10月17日

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号