JVM-类加载器

JVM-类加载器
JVM-类加载器

JAVA类加载器

目的

了解 Java 的类加载机制对我们熟练灵活运用 Java 语言,提高程序的运行效率有着非常重要的作用,知其然也要知其所以然,这样才能从整体提高程序的质量。

类加载器的体系结构

类装载器的体系结构在JAVA虚拟机的安全性和网络移动性发挥重要作用。在图中仅画了一个“类装载器”,实际上JAVA虚拟机种存在多个类装载器,因而图中的方框实际上是一个包含多个类装载器的子系统。

如图:

每个类装载器都有自己的命名空间。

JAVA加载类说明

当执行某个类的时候, java.exe 会帮助我们找到 JRE ,接着找到位于 JRE 内部的jvm.dll ,这才是真正的 Java 虚拟机器 , 最后加载动态库,激活 Java 虚拟机器。虚拟机器激活以后,会先做一些初始化的动作,比如说读取系统参数等。一旦初始化动作完成之后,就会产生第一个类加载器―― Bootstrap Loader , Bootstrap Loader 是由 C++ 所撰写而成,这个 Bootstrap Loader 所做的初始工作中,除了一些基本的初始化动作之外,最重要的就是加载 Launcher.java 之中的 ExtClassLoader ,并设定其 Parent 为 null ,代表其父加载器为BootstrapLoader 。然后Bootstrap Loader 再要求加载Launcher.java 之中的AppClassLoader ,并设定其Parent 为之前产生的ExtClassLoader 实体。这两个加载器都是以静态类的形式存在的。这里要请大家注意的是,Launcher$ExtClassLoader.class 与 Launcher$AppClassLoader.class 都是由 Bootstrap Loader 所加载,所以 Parent 和由哪个类加载器加载没有关系。

BootstrapLoader : sun.boot.class.path

ExtClassLoader: java.ext.dirs

AppClassLoader: java.class.path

执行java XXX.class的过程

找到JRE——》找到jvm.dll——》启动JVM并进行初始化——》产生Bootstrap Loader——》载入ExtClassLoader——》载入AppClassLoader——》执行java XXX.class

加载类工作原理

加载类采用的是全盘负责委托机制(双亲委托)。所谓全盘负责,即是当一个classloader加载一个Class的时候,这个Class所依赖的和引用的所有 Class也由这个classloader负责载入,除非是显式的使用另外一个classloader载入;委托机制则是先让parent(父)类加载器 (而不是super,它与parent classloader类不是继承关系)寻找,只有在parent找不到的时候才从自己的类路径中去寻找。此外类加载还采用了cache机制,也就是如果 cache中保存了这个Class就直接返回它,如果没有才从文件中读取和转换成Class,并存入cache,这就是为什么我们修改了Class但是必须重新启动JVM才能生效的原因。

ClassLoader加载Class的过程

类加载器对安全的作用

如一个JAVA应用程序,装载了一个类装载器,这个类装载器是通过网络下载装载某个class 文件。假设在我们自己的机器上运行这个应用程序,系统启动后,建立了以下双亲-孩子关系链:

装载某类最后会由网络类装载器完成。若某类中引用了java.util.HashMap,因为该类属于启动类加载器中,所以系统环境中该类有效。这就是安全潜在路径。

另外,JAVA允许在同一个包中的类拥有彼此特殊的访问权限,所以JAVA虚拟机又提出了一个运行时包的概念,不同类加载器加载的包,属于不同的类。每个类加载器,都有自己的权限,最高级别具有最高可信度。

类加载器的工作步骤

Java中,在调用类的静态成员,或新建该类的对象等之前,类一定要先装入Java

虚拟机中,这是勿庸置疑的。但虚拟机怎样把类装载进来的呢?要经过三步:装载(Load),链接(Link),初始化(Initializ)。其中链接又可分为校验(Verify),准备(Prepare),解析(Resolve)三步。

一、装载(Load)

ClassLoader就是用来装载的。通过指定的className,找到二进制码,生成Class 实例,放到JVM中。

ClassLoader从顶向下分为Bootstrap ClassLoader、Extension ClassLoader、System ClassLoader以及User-Defined ClassLoader(分叉,可以多个)。如下图。

这是Tomcat装载器的例子:

装载过程从源码清析可见:

protected synchronized Class loadClass(String name, boolean resolve) throws ClassNotFoundException

{

// 先检查是否已被当前ClassLoader装载。

Class c = findLoadedClass(name);

if (c == null) {

try {

if (parent != null) {

// 如果没被当前装载,则递归的到父中装载。

c = parent.loadClass(name, false);

} else {

// 装载器树已到顶,还没找到的话就到Bootstrap装载器中找。注意:虽然Bootstrap是所有加载器的根,但它是C++实现的,不可能放到子的"parent"中,因此,第二层装载器是所有的根了。

c = findBootstrapClass0(name);

}

} catch (ClassNotFoundException e) {

// 如果祖先都无法装载,则用当前的装载。子类可在findClass 方法中调用defineClass,把从自定义位置获得的字节码转换成Class。

c = findClass(name);

}

}

if (resolve) {

// Links the specified class.

resolveClass(c); //连接

}

return c;

}

注:

1.resolveClass(c)方法的注释是链接类,而不只是解析。

2.调用resolveClass时语义上是去链接,可以肯定的是没有初始化。当A类

中有static B b=new B()时,最晚会在初始化时去装载B。

二、链接

链接就是把load进来的class合并到JVM的运行时状态中。

链接是三个阶段中最复杂的一个。可以把它分成三个主要阶段:

校验。对二进制字节码的格式进行校验,以确保格式正确、行为正确。

如格式、长度、是否符合规范,符合超类接口等。

确保超类被加载。

?准备。准备类中定义的字段、方法和实现接口所必需的数据结构。比如会为类中的静态变量赋默认值(int等:0, reference:null,

char:'\u0000')。

准备时,还为类变量分配内存。

?解析。装入类所引用的其他所有类。可以用许多方式引用类:

?超类

?接口

?字段

?方法签名

?方法中使用的本地变量

符号引用换成直接引用。

三、初始化

Initialization of a class consists of executing its static initializers and the initializers for static fields (class variables) declared in the class. Initialization of an interface consists of executing the initializers for fields (constants) declared there.

类的初始化包括:执行静态区块和静态方法的初始化。比如下面这两种代码都会被执行,包括new B()。

static{

...

}

static B b=new B();

接口中不允许有static initializer(也就是static{...}),所以对于接口,只会执行静态字段的初始化。

初始化前,装载,链接一定已经执行过!

类初始化前,它的直接父类一定要先初始化(递归),但它实现的接口不需要先被初始化。类似的,接口在初始化前,父接口不需要先初始化。

什么情况下,类的初始化会被触发?

A class or interface type T will be initialized immediately before the first occurrence of any one of the following:

?

?T is a class and an instance of T is created.

?T is a class and a static method declared by T is invoked.

? A static field declared by T is assigned.

? A static field declared by T is used and the field is not a constant variable (§4.12.4).

?T is a top-level class, and an assert statement (§14.10) lexically nested within T is executed.

当使用类的字段时,即便可以通过子类或子接口访问该字段,但只有真正定义该字段的类会被触发初始化。如下例。

class Super { static int taxi = 1729; }

class Sub extends Super { static { System.out.print("Sub "); } }

class Test {

public static void main(String[] args) {

System.out.println(Sub.taxi);

}

}

只会输出“1729”,不会输出"Sub",也就是说,Sub其实没有被初始化。

四、Class.forName()与ClassLoader.loadClass()

这两方法都可以通过一个给定的类名去定位和加载这个类名对应的java.long.Class 类对象,区别如下:

1.初始化

Class.forName()会对类初始化,而loadClass()只会装载或链接。可见的效果就是类中静态初始化段及字节码中对所有静态成员的初始工作的执行(这个过程在类的所有父类中递归地调用). 这点就与ClassLoader.loadClass()不同. ClassLoader.loadClass()加载的类对象是在第一次被调用时才进行初始化的。

你可以利用上述的差异. 比如,要加载一个静态初始化开销很大的类, 你就可以选择提前加载该类(以确保它在classpath下), 但不进行初始化, 直到第一次使用该类的域或方法时才进行初始化

2.类加载器可能不同

Class.forName(String) 方法(只有一个参数), 使用调用者的类加载器来加载,

也就是用加载了调用forName方法的代码的那个类加载器。当然,它也有个重载的方法,可以指定加载器。相应的, ClassLoader.loadClass()方法是一个实例方法(非静态方法), 调用时需要自己指定类加载器, 那么这个类加载器就可能是也可能不是加载调用代码的类加载器(调用代用代码类加载器通getClassLoader0()获得)

参考《java虚拟机第二版.pdf》174页

URLClassLoader加载器

好了,现在我们了解了classloader的结构和工作原理,那么我们如何实现在运行时的动态载入和更新呢?只要我们能够动态改变类搜索路径和清除classloader的cache中已经载入的Class就行了,有两个方案,一是我们继承一个classloader,覆盖 loadclass方法,动态的寻找Class文件并使用defineClass方法来;另一个则非常简单实用,只要重新使用一个新的类搜索路径来new 一个classloader就行了,这样即更新了类搜索路径以便来载入新的Class,也重新生成了一个空白的cache(当然,类搜索路径不一定必须更改)。噢,太好了,我们几乎不用做什么工作,https://www.360docs.net/doc/f3693148.html,URLClassLoader正是一个符合我们要求的classloader!我们可以直接使用或者继承它就可以了!

这是j2se1.4 API的doc中URLClassLoader的两个构造器的描述:

URLClassLoader(URL[] urls)

Constructs a new URLClassLoader for the specified URLs using the default delegation parent ClassLoader.

URLClassLoader(URL[] urls, ClassLoader parent)

Constructs a new URLClassLoader for the given URLs.

其中URL[] urls就是我们要设置的类搜索路径,parent就是这个classloader的parent classloader,默认的是system classloader。

好,现在我们能够动态的载入Class了,这样我们就可以利用newInstance方法来获得一个Object。但我们如何将此Object造型呢?可以将此Object造型成它本身的Class吗?

weblogic的classloader装载策略及部署应用的目录结构

prefer-web-inf-classes

在web应用部署描述文件weblogic.xml 中,包含了元素prefer-web-inf-classes (container-descriptor 元素的子元素)。默认值被设置为false。设置这个元素的值未

true,从来改变类装载器的代理模式,提升子类装载器的级别,定义为首先从web应用中加载类。(然后从父类装载器中加载类)。这允许web应用来使用他们自己的第三方类库,这些类库也可能是weblogic应用服务器的。

当使用这一特性的时候,你必须小心,不要web应用的类的实例和服务器定义的实例混淆。否则就会产生ClassCastException 异常。

应用类装载器层次关系

weblogic Server自动建立类装载器层次当一个应用被部署的时候。层次中的根类装载器装载应用中所有EJB jar包中的文件,每个web应用(WAR)都会创建一个子类装载器。

当部署一个应用的时候,weblogic server会自动创建一个具有层次结构的类装载器。

在图中,a.Application Classloader负责装载应用中的所有的EJB JAR文件;

b.Web Application Classloader负责装载所有的Web application 中的WAR 文件(所有得jsp文件除外);

c.Jsp Classloader 负责装载Web application 中的所有的jsp 文件;

这样的分层结构有一个好处,就是在Jsp,Servlet中可以直接访问EJB的接口。这种上层装载EJB,下层装载servlet等,最下面装载jsp文件的结构,使得经常变动的jsp,servlet等可以被重新装载而不会涉及到EJB层。

在这种默认的类装载器结构下,有一点需要提出的是:

a. 我们的应用必须打包成一个EAR文件,才会允许我们应用中的jsp和servlet文件直接访问ejb;如果将WAR与JAR文件分别打包。Weblogic server 会为他们分别生成一个类装载器,作为兄弟节点,这时如果需要在jsp或者servlet 中使用ejb,就必须将EJB的Home接口与remote接口打包到WAR中才可以。后面这种情况,适合用在将EJB的客户端和EJB部署在不同的JVM中;

b.web application classloader中,不会装载jsp文件,jsp文件由web application classloader的子装载器Jsp classloader负责装载,因为jsp文件经常的变动,通过为jsp设立一个单独的classloader可以避免对jsp的装载影响到其他的java class或者ejb;

默认装载器的优点:

a. 调用ejb的时候可以采用call-by-referrence的方式;

b. 允许web module独立的装载,不影响其它的web module;

通过在将整个应用打包成一个EAR文件,可以方便的不用再web module中包含EJB的home和remote接口,就可以方便的通过call-by-referrence来调用ejb;

自定义模块类装载器层次关系

你为一个应用可以创建自定义的类装载器层次管理,以便更好的丛刊类的可见性和重新装载的能力。你通过在weblogic-application.xml 定义元素classloader-structure来构建。

下图详细说明了类装载器是如何被weblogic应用默认组织的。所有ejb类被装载时应用层的类装载器已经存在。每个WEB模块,都有一个子类装载器。

对于大多数应用来说这个层次是比较理想的,因为它允许参照调用ejb(不需要rmi)。它也允许web模块独立的重新装载而不影响其他模块,进一步说,它允许在一个web模块中运行的代码调用任何ejb模块。这个很方便,不需要web模块包含ejb的interface类。注意这些好处并不全部严格遵循J2EE规范。

The following is an example of a classloader declaration (defined in the classloader-structure element in weblogic-application.xml):

Listing 4-3 Example Classloader Declaration

ejb1.jar

web3.war

web1.war

ejb3.jar

web2.war

web4.war

ejb2.jar

The organization of the nesting indicates the classloader hierarchy. The above stanza leads to a hierarchy shown in the following diagram.

Figure 4-3 Example Classloader Hierarchy

架构中的使用说明

高级STARTUP

背景:为了在多个应用内共享配置

如何使用StartupForWeblogic初始化系统?

需要在weblogic的config.xml文件中增加以下配置:

ClassName="https://www.360docs.net/doc/f3693148.html,.jdls.foundation.startup.StartupForWeblogic"

Name="MyStartup Class" Targets="EjbServer"/>

如何一个DOMAIN下部署多个APPLICATION如何做到独立初始化?

需要在\WEB-INF\weblogic.xml文件中增加以下配置,要求Web应用优先加载WEB-INF 的Jar(即应用Classloader)而非WebLogic的System Classloader得以解决:

true

附录

以上是网上的引用,大家作为参考:

public class ClassLoaderTest1{

private ClassLoaderTest2 test = null;

public ClassLoaderTest1(){

test = new ClassLoaderTest2();

}

public void method(){

System.out.println("Loading ClassA");

}

}

class ClassLoaderTest2{

public ClassLoaderTest2(){

}

public void method(){

System.out.println("Loading ClassA");

}

}

测试程序:

URL url = null;

try {

url = new URL("file:/E:/JAVA/MyProject/string/");

} catch (MalformedURLException e) {

e.printStackTrace();

}

URLClassLoader cl = new URLClassLoader(new URL[]{url});

URLClassLoader cl1 = new URLClassLoader(new URL[]{url});

try {

Class tempClass = cl.loadClass("ClassLoaderTest1");

Class tempClass2 = cl.loadClass("ClassLoaderTest2");

Object test = tempClass.newInstance();

System.out.println(tempClass.getClassLoader());

System.out.println(tempClass2.getClassLoader());

} catch (Exception e) {

e.printStackTrace();

}

当ClassLoaderTest1,ClassLoaderTest2在当前目录和E:/JAVA/MyProject/string/都存在的时候输出为https://www.360docs.net/doc/f3693148.html,uncher$AppClassLoader@1050169

https://www.360docs.net/doc/f3693148.html,uncher$AppClassLoader@1050169

即都是被AppClassLoader加载的, 即使在E:/JAVA/MyProject/string/下面也存在.

当ClassLoaderTest1,ClassLoaderTest2只在E:/JAVA/MyProject/string/下存在的时候输出为

https://www.360docs.net/doc/f3693148.html,.URLClassLoader@480457

https://www.360docs.net/doc/f3693148.html,.URLClassLoader@1a7bf11

即都是被自定义的加载器加载的,并且也可以Object test = tempClass.newInstance();

下面一的是最关键的,因为ClassLoaderTest1需要用到ClassLoaderTest2,如果ClassLoaderTest2被AppClassLoader加载,而ClassLoaderTest1是被自定义的类加载器加载,就会出现如下错误:

https://www.360docs.net/doc/f3693148.html,ng.IllegalAccessError: tried to access class ClassLoaderTest2 from class ClassLoaderTest1

at ClassLoaderTest1. (ClassLoaderTest1.java:6)

at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)

at

sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessor Impl.java:39)

at

sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructor AccessorImpl.java:27)

at https://www.360docs.net/doc/f3693148.html,ng.reflect.Constructor.newInstance(Constructor.java:274)

at https://www.360docs.net/doc/f3693148.html,ng.Class.newInstance0(Class.java:308)

at https://www.360docs.net/doc/f3693148.html,ng.Class.newInstance(Class.java:261)

at ClassLoaderTest.main(ClassLoaderTest.java:43)

北大青鸟推荐:Java精选笔试题(含答案解析)

北大青鸟推荐:Java精选笔试题(含答案解析)如果你是计算机专业出生,但是还没有找到工作的话,你就得补补技术了,一些关于面试、笔试的题要多刷一刷。有可能你知道答案,但是由于语言组织能力有所欠缺,所以面试官的印象不是很好,下面分享一些Java精选的鄙视题,希望对面试这者有帮助。 1,volatile关键字是否能保证线程安全?() 答案:否 volatile关键字用在多线程同步中,可保证读取的可见性,JVM只是保证从主内存加载到线程工作内存的值是最新的读取值,而非cache中。但多个线程对volatile的写操作,无法保证线程安全。 假如线程1,线程2 在进行read,load 操作中,发现主内存中count的值都是5,那么都会加载这个最新的值,在线程1对count进行修改之后,会write到主内存中,主内存中的count变量就会变为6;线程2由于已经进行read,load操作,在进行运算之后,也会更新主内存count的变量值为6;导致两个线程及时volatile关键字修改之后,还是会存在并发的情况。 2,下面哪个流类属于面向字符的输入流( ) A、BufferedWriter B、FileInputStream C、ObjectInputStream D、InputStreamReader 答案:D Java的IO操作中有面向字节(Byte)和面向字符(Character)两种方式。

面向字节的操作为以8位为单位对二进制的数据进行操作,对数据不进行转换,这些类都是InputStream和OutputStream的子类。 面向字符的操作为以字符为单位对数据进行操作,在读的时候将二进制数据转为字符,在写的时候将字符转为二进制数据,这些类都是Reader和Writer的子类。 3,Java能不能不通过构造函数创建对象() A、能 B、不能 答案:A Java创建对象的几种方式: (1) 用new语句创建对象,这是最常见的创建对象的方法。 (2) 运用反射手段,调用https://www.360docs.net/doc/f3693148.html,ng.Class或者https://www.360docs.net/doc/f3693148.html,ng.reflect.Constructor类的newInstance()实例方法。 (3) 调用对象的clone()方法。 (4) 运用反序列化手段,调用java.io.ObjectInputStream对象的readObject()方法。 (1)和(2)都会明确的显式的调用构造函数;(3)是在内存上对已有对象的影印,所以不会调用构造函数;(4)是从文件中还原类的对象,也不会调用构造函数。 4,下列哪个叙述是正确的() A.子类继承父类的构造方法。 B.abstract类的子类必须是非abstract类。 C.子类继承的方法只能操作子类继承和隐藏的成员变量。 D.子类重写或新增的方法也能直接操作被子类隐藏的成员变量。 答案:C 子类是不继承父类的构造方法的,而是必须调用其父类的构造方法。

Java API 试题

永隆 JAVA笔试题 一、选择题 1、关于Java 类的加载过程,下面哪些描述是正确的() A、在 Java 中,有四种类型的类加载器:BootStrapClassLoader、ExtClassLoader、AppClassLoader 以及用户自定义的ClassLoader。//Extension ClassLoader, System ClassLoader+用户自定义的classloader B、使用 new 关键字创建类实例时,其实就显示地包含了类的加载过程 C、在 Java 中,类的实例化流程分为两个部分:类的加载和类的实例化。类的加载又分为显式加载和隐式加载。 D、Class.forName 来加载类时,是通过 ExtClassLoader进行加载的。 //system classLoader 加载 2、关于HashMap的实现机制,下面哪些描述是正确的() A、HashMap中key-value 当成一个整体进行处理,系统总是根据数组的坐标来获得key-value 的存储位置。//没有存储顺序,无下标之说! B、HashMap基于哈希表的 Map 接口的实现,允许使用 null 值和 null 键。 C、如果HashMap中,如果Key的hash相同的话,HashMap将会出错。//会替换相应的value D、HashMap每次容量的扩增都是以2的倍数来增加。//大约获得2倍的桶数! 3、下面的代码执行输出正确的是() 1. public class test( 2. public int aMethod()[ 3. static int i=0; 4. i++; 5. return I; 6. ) 7. public static void main (String args[]){ 8. test test = new test(); 9. test.aMethod(); 10.int j = test.aMethod(); 11.System.out.printIn(j); 12.] 13.} A. 编译错误 B. 编译成功,打印出是“0” C. 编译成功,打印出是“1” D. 编译成功,打印出是“2” A 4、如何获取下面表单 select

ClassLoader详解

ClassLoader详解 目录 1.什么是C LASS L OADER (2) 2.C LASS L OADER的层次 (2) 3.C LASS L OADER加载C LASS的过程 (5) 4.类加载器的顺序 (5) 5.JVM是如何来建立类加载器的结构 (6) 6.如何实现在运行时的动态载入和更新 (9) 7.为什么要扩展C LASS L OADER (14) 8.C LASS L OADER树和委托模型 (14) 9.U NLOADING?R ELOADING? (15) 10.由名字空间引发的 (16) 11.类的查询 (18) 12.一些重要的方法 (20) 13.怎么组装这些方法 (21) 14.J AV A 2中C LASS L OADER 的变动 (21) 15.类与数据 (22) 16.类加载器如何工作? (23) 17.名词解释 (27) 18.T IPS (27) 19.类加载原则概括: (29) 20.问题 (29) 21.其他 (34)

1.什么是ClassLoader 与普通程序不同的是,Java程序(class文件)并不是本地的可执行程序。当运行Java程序时,首先运行JVM(Java虚拟机),然后再把Java class加载到JVM 里头运行,负责加载Java class的这部分就叫做Class Loader。 JVM本身包含了一个ClassLoader称为Bootstrap ClassLoader,和JVM一样,Bootstrap ClassLoader是用本地代码实现的,它负责加载核心Java Class(即所有java.*开头的类)。另外JVM还会提供两个ClassLoader,它们都是用Java语言编写的,由Bootstrap ClassLoader加载;其中Extension ClassLoader负责加载扩展的Java class(例如所有javax.*开头的类和存放在JRE的ext目录下的类),Application ClassLoader负责加载应用程序自身的类。 术语“类加载”指的是找出一个给定类名的字节所在的位置并且将这些字节转换成Java类实例的过程。 2.ClassLoader的层次 bootstrap classloader | extension classloader | app classloader app classloader 的parent是extension classloader,extension classloader的parent 是bootstrap classloader,bootstrap classloader的parent 是Null。 继承结构: Bootstrap ClassLoader |__URLClassLoader |__ExtClassLoader |__AppClassLoader

类的加载

类从加载到虚拟机到卸载,它的整个生命周期包括:加载(Loading),验证(Validation),准备(Preparation),解析(Resolution),初始化(Initialization),使用(Using)和卸载(Unloading)。其中,验证、准备和解析部分被称为连接(Linking)。 加载: 在加载阶段,虚拟机主要完成三件事: 1.通过一个类的全限定名来获取定义此类的二进制字节流。 2.将这个字节流所代表的静态存储结构转化为方法区域的运行时数据结构。 3.在Java堆中生成一个代表这个类的https://www.360docs.net/doc/f3693148.html,ng.Class对象,作为方法区域数据的访问入口。 验证: 验证阶段作用是保证Class文件的字节流包含的信息符合JVM规范,不会给JVM造成危害。如果验证失败,就会抛出一个https://www.360docs.net/doc/f3693148.html,ng.VerifyError异常或其子类异常。验证过程分为四个阶段: 1.文件格式验证:验证字节流文件是否符合Class文件格式的规范,并且能被当前虚拟机正确的处理。 2.元数据验证:是对字节码描述的信息进行语义分析,以保证其描述的信息符合Java语言的规范。 3.字节码验证:主要是进行数据流和控制流的分析,保证被校验类的方法在运行时不会危害虚拟机。

4.符号引用验证:符号引用验证发生在虚拟机将符号引用转化为直接引用的时候,这个转化动作将在解析阶段中发生。 准备: 准备阶段为变量分配内存并设置类变量的初始化。在这个阶段分配的仅为类的变量(static修饰的变量),而不包括类的实例变量。对已非final的变量,JVM会将其设置成“零值”,而不是其赋值语句的值: pirvate static int size = 12; 那么在这个阶段,size的值为0,而不是12。final修饰的类变量将会赋值成真实的值。 解析: 解析过程是将常量池内的符号引用替换成直接引用。主要包括四种类型引用的解析。类或接口的解析、字段解析、方法解析、接口方法解析。 初始化: 在准备阶段,类变量已经经过一次初始化了,在这个阶段,则是根据程序员通过程序制定的计划去初始化类的变量和其他资源。这些资源有static{}块,构造函数,父类的初始化等。 至于使用和卸载阶段阶段,这里不再过多说明,使用过程就是根据程序定义的行为执行,卸载由GC完成。

字节跳动面试经验分享(非常详细)

字节跳动面试官一招差点KO我,一共面试了3轮(5年经验),艰难拿下2-2职级offer! 前言 我从大学毕业开始做Android开发,现在已经五年时间了,现在在山东老家济南做Android开发。这三年里面,也只是一心在做Android开发,其他语言接触的并不多,了解点JS之类的。现在感觉Android开始不像以前那样好做了,也可能是现在年纪慢慢大了,要考虑的事情变多了的缘故吧。 不知道以后应该何去何从,总是感觉做Android或者说做程序员一直处在一种不稳定之中,在一些中小公司里面,可能工作一年两年就因为各种各样的原因而离职。马上就要结婚了,该买房了。济南的房价一直在涨,而自己的收入还是这么不温不火的,加上这不稳定的工作,让人对于前途实在是乐观不起来。 再加上今年的大环境非常差,互联网企业裁员的现象比往年更严重了,可今年刚好是我的第一个“五年计划”截止的时间点,说什么也不能够耽搁了,所以早早准备的跳槽也在疫情好转之后开始进行了。但是,不得不说,这次字节的面试真的太难为我了,可以说是和面试官大战了3个回合,不过好在最后给了offer。 我个人情况是5年Android开发经验,字节跳动定级2-2(年薪是50-100w左右含加班费和股票折现,不含车餐房补)的样子,我是拿到了年薪60w+,13薪。下面是我的面试经历,与学习经验分享,希望能带来一些不一样的启发和帮助。 我与字节跳动面试官“大战”3回合,胜! 我的学习经验 1—4年大学 ?Java

无论什么级别的Android从业者,Java作为Android开发基础语言。不管是工作还是面试中,Java都是必考题。如果不懂Java的话,薪酬会非常吃亏(美团尤为重视Java基础) 详细介绍了Java泛型、注解、并发编程、数据传输与序列化、高效IO、容器集合、反射与类加载以及JVM重点知识线程、内存模型、JVM运行时内存、垃圾回收与算法、Java中四种引用类型、GC 分代收集算法 VS 分区收集算法、GC 垃圾收集器、JAVA IO/NIO 、JVM 类加载机制的各大知识点。 ?筑基必备 Android架构师筑基包括哪些内容呢: 1.深入 Java 泛型. 2.解深入浅出 3.并发编程 4.数据传输与序列化 5.Java 虚拟机原理 6.反射与类加载 7.高效 IO 8.Kotlin项目实战 大学1-4年架构师筑基必备 ?学习笔记整理 架构师筑基必备目录 架构师筑基必备第一章

【IT专家】来自加载类的Java Call类函数

本文由我司收集整编,推荐下载,如有疑问,请与我司联系 来自加载类的Java Call类函数 2011/02/25 1277 How would I, if possible, call a function in my Main class in the class that I load? (I know that is impossible to understand, so I’ll explain) ?如果可能的话,我如何在我加载的类中调用Main类中的函数? (我知道这是不可能理解的,因此我会解释) I.E: public class SomeClass public SomeClass //load a class here public void FuncToCall() {}//In a separate file, dynamically loaded.public class LoadedClass public LoadedClass //Call a function in the class that loads this SomeClass.FuncToCall(); So I would end up having 2 files: SomeClass.class and LoadedClass.class. I guess my main question is, how do I reference SomeClass in LoadedClass? ?因此我最终会得到2个文件:SomeClass.class和LoadedClass.class。我想我的主要问题是,如何在LoadedClass中引用SomeClass? **EDIT: So maybe I should better explain the use case. A java program dynamically loads the “SomeClass” script from a folder. The script then downloads a .jar file from the internet and opens and runs the “LoadedClass” script within that. How do I use functions in SomeClass in LoadedClass if SomeClass isn’t in the same .jar or in a .jar at all? ?因此也许我应该更好地解释用例。java程序从文件夹动态加载“SomeClass”脚本。然后,该脚本从Internet下载.jar文件,并在其中打开并运行“LoadedClass”脚本。如果SomeClass不在同一个.jar或.jar中,我如何在LoadedClass中的SomeClass中使用函数? ?你这样做.. ?If they are in different packages you have to either import the class or use the fully qualified name. ?如果它们位于不同的包中,则必须导入该类或使用完全限定的名称。

java如何写存储过程

Java中对存储过程的调用 一:Java如何实现对存储过程的调用: A:不带输出参数的 ---------------不带输出参数的---------------------------------- create procedure getsum @n int =0<--此处为参数--> as declare @sum int<--定义变量--> declare @i int set @sum=0 set @i=0 while @i<=@n begin set @sum=@sum+@i set @i=@i+1 end print 'the sum is '+ltrim(rtrim(str(@sum))) --------------在SQL中执行:-------------------- exec getsum 100 ------------在JAVA中调用:--------------------- JAVA可以调用但是在JAVA程序却不能去显示该存储过程的结果因为上面的存储 过程的参数类型int 传递方式是in(按值)方式 import java.sql.*; public class ProcedureTest { public static void main(String args[]) throws Exception { //加载驱动 DriverManager.registerDriver(new sun.jdbc.odbc.JdbcOdbcDriver()); //获得连接 Connection conn=DriverManager.getConnection("jdbc:odbc:mydata","sa",""); //创建存储过程的对象 CallableStatement c=conn.prepareCall("{call getsum(?)}"); //给存储过程的参数设置值 c.setInt(1,100); //将第一个参数的值设置成100 //执行存储过程 c.execute(); conn.close();

Java程序是如何运行的

Java程序是如何运行的 JVM是Java的运行时虚拟机,所有的Java程序都是在JVM沙箱中运行,每个Java程序就是一个独立的JVM进程。 谈到Java程序是如何运行的,首先需要理解的肯定是JVM是如何运行的,什么是JVM;要理解我们编写的Java程序,运行起来以后到底是什么样子,本质上就是弄清楚JVM是什么样子。 Java程序的代码是什么样的 Java诞生之初最大的卖点就是编写的代码跨平台可移植性,实现这种可移植性,是因为Java通过平台特定的虚拟机,运行中间的字节码,而不是直接编译成本地二进制代码实现,中间字节码也就是java文件编译后生成的.class文件,Jar包的话,实际上只是一系列.class文件的集合。 编写Java程序,首先需要一个入口点,在运行的时候通过指定MainClass来指定入口点,代码层面主类必须实现一个静态的main函数,运行时虚拟机会从MainClass.main开始执行指令,其他的逻辑只是import和函数调用了。 SDK自带的javac命令,负责将我们编程的Java代码,也就是.java文件,编译成平台无关的字节码;字节码可以在任何操作系统平台上,通过平台对应的JVM执行;JVM执行的时候,运行字节码,根据自己的平台特性,将字节码转换成平台相关的二进制码运行。 javac编译器运行的过程大致分为:词法分析(Token流)、语法分析(语法树)、语义分析(注解语法树),还有代码生成器,根据注解语法树,生成字节码, 语义分析阶段,编译器会做一些操作,将人类友好的代码,做一些处理,转换成更符合机器执行机制的代码,例如全局变量,魔法变量,依赖注入,注解这些魔法机制。大致分为以下步骤: 1. 给类添加默认构造函数 2. 处理注解 3. 检查语义的合法性并进行逻辑判断 4. 数据流分析 5. 对语法树进行语义分析(变量自动转换并去掉语法糖) JVM是什么 JVM = 类加载器 classloader + 执行引擎 execution engine + 运行时数据区域 runtime data area JVM就是运行编译好字节码的虚拟机,不同的操作系统和平台上,虚拟机将平台无关的字节码,编译成特定平台的指令去执行。我觉得,JVM首先是一个独立运行在操作系统上的进程。执行java命

java多选题

java多选题 多选题 1、下列选项代码正确的有()。 A、 int i=0; if (i) { System.out.println(“OK”); } B、 boolean b=true; boolean b2=true; if(b==b2) { System.out.println(“OK”); } C、 int i=1; int j=2; if(i==1 &| j==2) System.out.println(“OK”); D、 int i=1; int j=2; if (i==1 || j==2) System.out.println(“OK”); 解答:B, D 知识点:3.3 Java语言算术运算符、关系运算符、逻辑运算符、位运算符和复合赋值运算符的功能及使用; 2、下面哪三项演示了继承关系(is a)?() A、interface Component{ } class Container extends Component{} B、class Father { } class son extends Father { } C、abstract class Colorable { } class Shape extends Colorable { } D、public class Species{ } public class Animal{private Species species;} E、interface Person { } public class Employee implements Person{ } 解答:B,C,E 知识点:5.3 Java 父类与子类、域继承和方法继承的操作过程。

Java的数据结构相关的类实现原理

Java的数据结构相关的类实现原理 List接口 List是有序的Collection,使用此接口能够精确的控制每个元素插入的位置。用户能够使用索引(元素在List中的位置,类似于数组下标)来访问List中的元素,这类似于Java的数组。 和下面要提到的Set不同,List允许有相同的元素。 除了具有Collection接口必备的iterator()方法外,List还提供一个listIterator()方法,返回一个ListIterator接口,和标准的Iterator接口相比,ListIterator多了一些add()之类的方法,允许添加,删除,设定元素,还能向前或向后遍历。 实现List接口的常用类有LinkedList,ArrayList,Vector和Stack。 LinkedList List 接口的链接列表实现。实现所有可选的列表操作,并且允许所有元素(包括 null)。除了实现 List 接口外,LinkedList 类还为在列表的开头及结尾 get、remove 和 insert 元素提供了统一的命名方法。这些操作允许将链接列表用作堆栈、队列或双端队列。 此类实现 Deque 接口,为 add、poll 提供先进先出队列操作,以及其他堆栈和双端队列操作。 所有操作都是按照双重链接列表的需要执行的。在列表中编索引的操作将从开头或结尾遍历列表(从靠近指定索引的一端)。 注意,此实现不是同步的。如果多个线程同时访问一个链接列表,而其中至少一个线程从结构上修改了该列表,则它必须保持外部同步。(结构修改指添加或删除一个或多个元素的任何操作;仅设置元素的值不是结构修改。)这一般通过对自然封装该列表的对象进行同步操作来完成。如果不存在这样的对象,则应该使 用 Collections.synchronizedList 方法来“包装”该列表。最好在创建时完成这一操作,以防止对列表进行意外的不同步访问,如下所示: List list = Collections.synchronizedList(new LinkedList(...)); 此类的 iterator 和 listIterator 方法返回的迭代器是快速失败的:在迭代器创建之后,如果从结构上对列表进行修改,除非通过迭代器自身的remove 或 add 方法,其他任何时间任何方式的修改,迭代器都将抛 出 ConcurrentModificationException。因此,面对并发的修改,迭代器很快就会完全失败,而不冒将来不确定的时间任意发生不确定行为的风险。 注意,迭代器的快速失败行为不能得到保证,一般来说,存在不同步的并发修改时,不可能作出任何硬性保证。快速失败迭代器尽最大努力抛出ConcurrentModificationException。因此,编写依赖于此异常的程序的方式是错误的,正确做法是:迭代器的快速失败行为应该仅用于检测程序错误。 ArrayList

java类加载机制

Java类加载机制(一) 译:ayi 第一次翻译,翻译得不是很好,请多多指点 我的邮箱:nonopo12345@https://www.360docs.net/doc/f3693148.html, 原文:https://www.360docs.net/doc/f3693148.html,/pub/a/onjava/2005/01/26/classloading.html 类加载是java特性的一个重量级的组成部分。尽管,java中“advanced topics”的发展,使java的类加载机制的地位有所下降。但每位编程着都应该知道这部分的工作机制,以及怎样去更好与其配合。这可以使我们节省很多时间,二不必要浪费在调试ClassNotFoundException, ClassCastException, 等。 这篇文章将从最基本的开始,比如代码和数据的关系和区别,以及他们怎么样关系起来形成一个实例或者对象。然后将会说到,java中怎样通过类加载器把代码加载到JVM中,以及java中实现的主要的几种类型的类加载器。然后在这篇文章中我们将会了解到java类加载机制的内幕,我们将使用最基本的代码来描述,这些代码执行与类加载器之后,但在加载一个类之前。在接下来的部分将使用一些例子来强调,对于开发者继承和开发自己的类加载器的必要性。接着将告诉你们怎样编写自己的类加载器,以及怎样使用它们去创建一个一般的能加载包括远程客户端辅助代码的类加载器引擎,以及怎样把它在JVM中定义,实例化,然后执行。习惯上,把J2EE-specific components 中说明的作为java类加载的规范,这篇文章正是从这本手册总结来的。 类和数据 一个类代表一段要执行的代码,然而数据则代表与这些代码相关联的某种状态。状态可以改变,代码不能改变。我们把一种特定状态与一个类关联起来时,就得到了这个类的一个实例。所以同一个类的不同实例有不同的状态,但都参照相同的代码。在java中,一个类通常它的代码就包含在一个 .class 文件中,虽然其中也包括异常。然而,在java运行时,每个类都会构造一个超类对象(first-class object),它们其实是https://www.360docs.net/doc/f3693148.html,ng.Class的实例。不论何时编译一个java文件,编译器都会在编译后的字节码中嵌入一个public, static, final型的字段class,这个字段表示的就是一个https://www.360docs.net/doc/f3693148.html,ng.Class型的实例。因为它是public类型的,我们可以通过标识符来访问它,像这样: https://www.360docs.net/doc/f3693148.html,ng.Class klass = Myclass.class; 只要一个类被加载到JVM,相同的类(强调:相同的类)将不会被重复加载。这将产生一个问题,什么才是相同的类?一个对象有一种特定状态和标识,对象总是与它所属类联系在一起,与这种状况相似,一个被加载到JVM中类也有特定的标识,接下来我们就阐述: 在java中,一个类通过认证的类全名来唯一标识。认证的类全名是由包名和类名两部分组

java实验指导书

实验一java开发环境及语言基础 实验目的 (1)确保正确配置java开发环境。 (2)了解javac和java命令的使用。 (3)熟悉java中的运算符。 (4)掌握条件语句和循环语句的使用。 (5)掌握通过命令行参数接受数据。 (6)掌握用Scanner类接受数据。 实验内容 (1)在控制台中输入java命令,查看输入结果。 (2)编写一个java程序,计算半径为3.0的圆周长和面积并输出结果。 (3)求a+aa+aaa+...+a...a(n个)的和,其中a为1~9之间的整数。例如,当a=3、n=4时,求3+33+333+3333的和。 (4)给定一个正整数m,统计其位数,分别打印每一位数字,再按照逆序打印出各位数字。(5)用Scanner类方法输入三角形三边求三角形面积。 实验要求 (1)JDK的安装及配置。 (2)在DOS及eclipse下编辑、编译运行第一个java程序:hello world。 (3)求圆周长和面积用方法实现,主函数调用。 (4)从命令行输入1~9之间的整数a,当所求的和大与106时,输出相应的a值及所求的和值。 (5)用Scanner类的方法输入正整数m,m的值不应该超过99999,否则给出错误信息。应引入包:import java.util.Scanner,然后在需要的方法中实例化对象:Scanner sc = new Scanner(System.in),最后调用对象的next方法,如int n=nextInt(),接受整数。 实验二数组 实验目的 (1)掌握数组的定义和使用方法。 (2)熟悉数组的排序、查找的方法。 (3)巩固循环的使用。 实验内容 (1)使用for循环,将二维数组的行与列互换,即完成矩阵的转置。 (2)编写数组的排序程序。 (3)编写杨辉三角。 实验要求 (1)编写一个界面1 选择排序2 冒泡排序3插入排序4 快速排序5 退出 当选择1、2、3、4、5的时候完成相应的功能。 (2)杨辉三角形状为等腰三角形 实验三字符串 实验目的 (1)掌握正则表达式的使用。 (2)熟悉java的字符串。

java 使用tomcat类加载器加载类,找不到加载器

The Tomcat installation directory is not valid. It is missing expected file or folder common/i18n. eclipse 配置使用apache-tomcat-5.5.34时,提示如上。 换了个apache-tomcat-5.5.29 的版本。 但是加载启动项目时,出现类加载器无法加载类。因为apache-tomcat-5.5.29 版本中缺少类加载器的类。 Caused by: https://www.360docs.net/doc/f3693148.html,ng.ClassNotFoundException: org.apache.catalina.loader.WebappLoader 在\apache-tomcat-5.5.29\conf\Catalina\localhost 下会有项目配置的比如project.xml运行生成。这样启动的时候才会把项目加载上。 在eclipse\plugins\com.sysdeo.eclipse.tomcat_3.2.1 找到DevLoader.zip 文件夹。 1、在eclipse目录下,找到DevLoader包,位于 eclipse\plugins\com.sysdeo.eclipse.tomcat_3.2.1的DevLoader.zip 2、复制DevLoader.zip到Tomcat apache-tomcat-5.5.29 的\lib下。 3、解压缩DevLoader.zip在当前文件夹,然后把\DevLoader 下的org文件夹全部copy到\apache-tomcat-5.5.29\server\classes下。必须是server\classes 下,而不能是apache-tomcat-5.5.29\common\classes 下。

Java开源架构技术学习重点(部分答案版)(1)

第一章 Strut2框架技术的入门 1、Struts2的是怎么产生的? Struts2是Struts的下一代产品,是在Struts1和WebWork的技术基础上进行了合并,全新的Struts2框架。其全新的Struts2的体系结构与Struts1的体系结构的差别巨大。Struts 2以WebWork为核心,采用拦截器的机制来处理用户的请求,这样的设计也使得业务逻辑控制器能够与Servlet API完全脱离开,所以Struts 2可以理解为WebWork的更新产品。因此Struts2和Struts 1有着太大的变化,但是相对于WebWork,Struts2只有很小的变化。 2、Struts2的设计模式是什么?采用这种设计模式有什么好处? MVC模式 MVC模式对于Web应用的开发无疑是一种非常先进的设计思想,无论选择 哪种语言,无论应用多复杂,它都能为理解分析应用模型提供最基本的分析方法, 为构造产品提供清晰的设计框架,为软件工程提供规范的依据。 1. 模型(Model) Model 部分包括业务逻辑层和数据库访问层。在Java Web 应用程序中,业务逻辑层一般由JavaBean或EJB构建。Model 部分就是业务流程或状态的处理以及业务规则的制定。业务流程的处理过程对其他层来说是黑箱操作,模型接受视图请求的数据,并返回最终的处理结果。业务模型的设计可以说是MVC最主要的组件。MVC并没有提供模型的设计方法,而只提供给用户应该组织管理这些模型,以便于模型的重构和提高重用性。 2. 视图(View) 在Java Web 应用程序中,View 部分一般用JSP 和HTML 构建,也可以是XHTML、XML、Applet和JavaScript。客户在View 部分提交请求,在业务逻辑层处理后,

JAVA判断题含答案

判断题 1. 利用equals()方法判定Date类时,判断的是对象的值而不是对象的地址。 A. 错误 B. 正确 2. 类加载器加载程序运行所需要的所有类,它通过区分本机文件系统的类和网络系统导入的类增加安全性。 A. 错误 B. 正确 1. == 操作符判定两个分立的对象的内容和类型是否一致。 A. 错误 B. 正确 2. 类加载器加载程序运行所需要的所有类,由网络系统导入的指定类总是先被加载。 A. 错误 B. 正确 1. equals()方法只有在两个对象的内容一致时返回true。 A. 错误 B. 正确 2. 调用System.gc()方法不能保证JVM立即进行垃圾收集,而只能是建议。 A. 错误 B. 正确 1. friendly关键字是Java语言的访问控制修饰符。 A. 错误 B. 正确 2. maxElements是一个成员变量,声明为:“public static final int maxElements=100;”。 A. 错误 B. 正确

3. 实例变量在使用new Xxxx()创建该类的实例时被创建,而其生存期和该类的实例对象的生存期相同。 A. 错误 B. 正确 4. 在构造方法中如调用super()语句,则必须使其成为构造方法中的第一条语句。 A. 错误 B. 正确 5. 重写的方法的访问权限不能比被重写的方法的访问权限高。 A. 错误 B. 正确 6. 类变量在该类被加载时被创建,不能用new Xxxx()创建,所有该类的实例对象共享类变量,其生存期是类的生存期。 A. 错误 B. 正确 7. 调用sleep()方法可以使一个线程停止运行。 A. 错误 B. 正确 8. 一个新线程启动start()方法,表示线程可为JVM的线程调度程序调度而不表示它可以立即运行。 A. 错误 B. 正确 9. 垃圾收集的过程在Java程序的生存期中是自动的,不需要分配和释放内存,也避免了内存泄漏。 A. 错误 B. 正确 10. equals()方法只有在两个对象的内容一致时返回true。 A. 错误 B. 正确

JAVA笔试题1

知识点: (1) 1.面向对象的软件开发有哪些优点? (1) 2.什么叫对象?什么叫类?类和对象有什么关系。 (1) 3.什么是包?把一个类放在包里有什么作用? (2) 4.作用域public、private、protected以及不写时(default)有什么区别? (2) 5.什么是方法?方法的结构是怎样的?设计方法应考虑哪些因素? (2) 6.什么是方法的覆盖?与方法的重载有何不同?方法的覆盖与属性的隐藏有何不同? (3) 7.什么是成员变量、局部变量、类变量和实例变量? (3) 8.什么是继承?什么是父类?什么是子类?继承的特性可给面向对象编程带来什么好处? (3) 9.什么是多态?面向对象程序设计为什么要引入多态的特性? (4) 10.“子类的域和方法的数目一定大于等于父类的域和方法的数目”,这种说法是否正确?为什么? (4) 11.父类对象与子类对象相互转化的条件是什么?如何实现它们的相互转化? (4) 12.接口与抽象类有哪些异同点? (4) 13.区分接口与抽象类分别在什么场合使用? (5) 14.一个类如何实现接口?实现某接口的类是否一定要重载该接口中的所有抽象方法? (5) 15.进程与线程的区别与联系? (5) 编程: (6) 1.统计一个字符串中出现某个字母的次数(注意区分大小写)。 (6) 2.编写一个程序,在主类中创建和调用方法sumf(),方法sumf()的功能是进行两个浮点数的加法运算。6知识点: 1.面向对象的软件开发有哪些优点? 面向对象设计是一种把面向对象的思想应用于软件开发过程中,指导开发活动的系统方法,是建立在“对象”概念基础上的方法学。所谓面向对象就是基于对象概念,以对象为中心,以类和继承为构造机制,来认识、理解、刻画客观世界和设计、构建相应的软件系统。 从面向过程到面向对象是程序设计技术的一个飞跃。人们之所以要采用面向对象的程序设计技术,其目的在于:按照与人类习惯思维方法一致的原则开发系统;提高代码的可重用性(或者称为复用性);提升程序的开发与运行效率;提高程序的可靠性与可维护性;提高程序的可扩展性;增强程序的可控制性。总之,面向对象的程序设计,能够有效分解、降低问题的难度与复杂性,提高整个求解过程的可控制性、可监视性和可维护性,从而获得较高的开发效率与可靠效果。 2.什么叫对象?什么叫类?类和对象有什么关系。 对象(Object)是一个应用系统中用来描述客观事物的实体,是具有特定属性(数据)和行为(方法)的基本运行单位,是类的一个特定状态下的实例。对象是一件事、一个实体、一个名词、一个可以想象为有自己的标识的任何东西。对象是类的实例化。概括来说:万物皆对象。对象具有状态,一个对象用数据值来描述它的状态。 类(Class)是Java代码的基本组织模块,是用以描述一组具有共同属性和行为的对象的基本原型,是对这组对象的概括、归纳与抽象表达。类是对象的模板,它定义了本类对象所应拥有的状态属性集及操作这组属性的行为方法集。是对一组有相同数据和相同操作的对象的定义,一个类所包含的方法和数据描述一组对象的共同属性和行为。

JAVA类与对象的创建

试验四 类和对象的创建 一.类的定义 类是组成Java程序的基本要素。类封装了一类对象的状态和方法。类用来定义对象的模板。 类的实现包括两部分:类声明和类体。基本格式为: 修饰符class类名[extends父类名]{ /*类体的内容*/ } 1.类声明 以下是一个类声明的例子。 class People成为类声明,People是类名。习惯上,类名的第一个字母大写,但这不是必须的。类的名字不能是Java中的关键字,要符合标识符规定,即类的名字可以由字母、下划线、数字或美元符号组成,并且第一个字母不能是数字。但给类命名时,最好遵守下列规则: (1)如果类名使用拉丁字母,那么名字的首写字母使用大写字母,如Hello、Time、People等。 (2)类名最好容易识别,当类名由几个“单词”复合而成时,每个单词的首写字母使用大写,如BeijingTi me、AmericanGame、HelloChina等。 2.类体 编写类的目的是为了描述一类事物共有的属性和功能,描述过程由类体来实现。类声明之后的一对大括号“{”、“}”以及它们之间的内容称为类体,大括号之间的内容称为类体的内容。 类体的内容由两部分构成:一部分是变量的定义,用来刻画属性;另一部分是方法的定义,用来刻画功能。 下面是一个类名为“Trapezia”的类,类体内容的变量定义部分定义了4个float类型变量:top、bottom、h igh和laderArea,方法定义部分定义了两个方法:“getArea”和“setHigh”。

二.对象 1.对象的创建 创建一个对象包括对象的声明和为对象分配内存两个步骤。 (1)对象的声明。 一般格式为: 类的名字对象名字; 如: 这里People是类的名字,zhubajie是我们声明的对象的名字。 (2)为声明的对象分配内存。 使用new运算符和类的构造方法为声明的对象分配内存,如果类中没有构造方法,系统会调用默认的构造方法(你一定还记得构造方法的名字必须和类名相同这一规定),如: 例1: 「注」如果类里定义了一个或多个构造方法,那么Java不提供默认的构造方法。 2.对象的使用 对象不仅可以改变自己变量的状态,而且还拥有了使用创建它的那个类中的方法的能力,对象通过使用这些方法可以产生一定的行为。 通过使用运算符“.”,对象可以实现对自己的变量访问和方法的调用。 例2:

Spring中ApplicationContext加载机制

Spring中ApplicationContext加载机制。 加载器目前有两种选择:ContextLoaderListener和ContextLoaderServlet。 这两者在功能上完全等同,只是一个是基于Servlet2.3版本中新引入的Listener接口实现,而另一个基于Servlet接口实现。开发中可根据目标Web容器的实际情况进行选择。 配置非常简单,在web.xml中增加: org.springframework.web.context.ContextLoaderListener 或: context org.springframework.web.context.ContextLoaderServlet 1 通过以上配置,Web容器会自动加载/WEB-INF/applicationContext.xml初始化ApplicationContext实例,如果需要指定配置文件位置,可通过context-param加以指定: contextConfigLocation /WEB-INF/myApplicationContext.xml 配置完成之后,即可通过 WebApplicationContextUtils.getWebApplicationContext方法在Web应用中获取ApplicationContext引用。 如:ApplicationContext ctx=WebApplicationContextUtils.getWebApplicationContext(); LoginAction action=(LoginAction)ctx.getBean("action"); ============================= Spring中WebApplicationContext的研究 ApplicationContext是Spring的核心,Context我们通常解释为上下文环境,我想用“容器”来表述它更容易理解一些,ApplicationContext则是“应用的容器”了,Spring把Bean 放在这个容器中,在需要的时候,用getBean方法取出,虽然我没有看过这一部分的源代码,但我想它应该是一个类似Map的结构。 在Web应用中,我们会用到WebApplicationContext,WebApplicationContext继承自ApplicationContext,先让我们看看在Web应用中,怎么初始化WebApplicationContext,

相关文档
最新文档