打印

[Java] 子若的JAVA入门本本

子若的JAVA入门本本

JAVA基础知识精华总结1、对象的初始化
(1)非静态对象的初始化  
  
在创建对象时,对象所在类的所有数据成员会首先进行初始化。   
基本类型:int型,初始化为0。  

如果为对象:这些对象会按顺序初始化。
※在所有类成员初始化完成之后,才调用本类的构造方法创建对象。   
构造方法的作用就是初始化。  
(2)静态对象的初始化  
程序中主类的静态变量会在main方法执行前初始化。  

不仅第一次创建对象时,类中的所有静态变量都初始化,并且第一次访问某类(注意此时未创建此类对象)的静态对象时,所有的静态变量也要按它们在类中的顺序初始化。   

2、继承时,对象的初始化过程   

(1)主类的超类由高到低按顺序初始化静态成员,无论静态成员是否为private。   
  
(2)主类静态成员的初始化。   

(3)主类的超类由高到低进行默认构造方法的调用。注意,在调用每一个超类的默认构造方法前,先进行对此超类进行非静态对象的初始化。  

(4)主类非静态成员的初始化。  
  
(5)调用主类的构造方法。  
  
3、关于构造方法   
  
(1)类可以没有构造方法,但如果有多个构造方法,就应该要有默认的构造方法,否则在继承此类时,需要在子类中显式调用父类的某一个非默认的构造方法了。  

(2)在一个构造方法中,只能调用一次其他的构造方法,并且调用构造方法的语句必须是第一条语句。
4、有关public、private和protected

(1)无public修饰的类,可以被其他类访问的条件是:a.两个类在同一文件中,b.两个类在同一文件夹中,c.两个类在同一软件包中。
(2)protected:继承类和同一软件包的类可访问。
(3)如果构造方法为private,那么在其他类中不能创建该类的对象。 
5、抽象类
(1)抽象类不能创建对象。
(2)如果一个类中一个方法为抽象方法,则这个类必须为abstract抽象类。
(3)继承抽象类的类在类中必须实现抽象类中的抽象方法。
(4)抽象类中可以有抽象方法,也可有非抽象方法。抽象方法不能为private。
(5)间接继承抽象类的类可以不给出抽象方法的定义。
6、final关键字
(1)一个对象是常量,不代表不能转变对象的成员,仍可以其成员进行操作。
(2)常量在使用前必须赋值,但除了在声明的同时初始化外,就只能在构造方法中初始化。
(3)final修饰的方法不能被重置(在子类中不能出现同名方法)。
(4)如果声明一个类为final,则所有的方法均为final,无论其是否被final修饰,但数据成员可为final也可不是。
7、接口interface(用implements来实现接口)
(1)接口中的所有数据均为static和final即静态常量。尽管可以不用这两个关键字修饰,但必须给常量赋初值。
(2)接口中的方法均为public,在实现接口类中,实现方法必须可public关键字。
(3)如果使用public来修饰接口,则接口必须与文件名相同。
8、多重继承 
(1)一个类继承了一个类和接口,那么必须将类写在前面,接口写在后面,接口之间用逗号分隔。

(2)接口之间可多重继承,注意使用关键字extends。

(3)一个类虽只实现了一个接口,但不仅要实现这个接口的所有方法,还要实现这个接口继承的接口的方法,接口中的所有方法均须在类中实现。
  
9、接口的嵌入   

(1)接口嵌入类中,可以使用private修饰。此时,接口只能在所在的类中实现,其他类不能访问。  

(2)嵌入接口中的接口一定要为public。   
  
10、类的嵌入   

(1)类可以嵌入另一个类中,但不能嵌入接口中。   
}  
(2)在静态方法或其他方法中,不能直接创建内部类对象,需通过手段来取得。   

手段有两种:  
  
class A { class B {} B getB() { B b = new B(); return b; } } static void m() { A a = new A(); A.B ab = a.getB(); // 或者是 A.B ab = a.new B(); }   
  

(3)一个类继承了另一个类的内部类,因为超类是内部类,而内部类的构造方法不能自动被调用,这样就需要在子类的构造方法中明确的调用超类的构造方法。接上例:  
  
class C extends A.B { C() { new A().super(); // 这一句就实现了对内部类构造方法的调用。 } }  


构造方法也可这样写:

C(A a) { a.super(); } // 使用这个构造方法创建对象,要写成C c = new C(a); a是A的对象。

11、异常类JAVA中除了RunTimeException类,其他异常均须捕获或抛出。


1、对象的初始化
(1)非静态对象的初始化  
  
在创建对象时,对象所在类的所有数据成员会首先进行初始化。   
基本类型:int型,初始化为0。  

如果为对象:这些对象会按顺序初始化。
※在所有类成员初始化完成之后,才调用本类的构造方法创建对象。   
构造方法的作用就是初始化。  
(2)静态对象的初始化  
程序中主类的静态变量会在main方法执行前初始化。  

不仅第一次创建对象时,类中的所有静态变量都初始化,并且第一次访问某类(注意此时未创建此类对象)的静态对象时,所有的静态变量也要按它们在类中的顺序初始化。   

2、继承时,对象的初始化过程   

(1)主类的超类由高到低按顺序初始化静态成员,无论静态成员是否为private。   
  
(2)主类静态成员的初始化。   

(3)主类的超类由高到低进行默认构造方法的调用。注意,在调用每一个超类的默认构造方法前,先进行对此超类进行非静态对象的初始化。  

(4)主类非静态成员的初始化。  
  
(5)调用主类的构造方法。  
  
3、关于构造方法   
  
(1)类可以没有构造方法,但如果有多个构造方法,就应该要有默认的构造方法,否则在继承此类时,需要在子类中显式调用父类的某一个非默认的构造方法了。  

(2)在一个构造方法中,只能调用一次其他的构造方法,并且调用构造方法的语句必须是第一条语句。
4、有关public、private和protected

(1)无public修饰的类,可以被其他类访问的条件是:a.两个类在同一文件中,b.两个类在同一文件夹中,c.两个类在同一软件包中。
(2)protected:继承类和同一软件包的类可访问。
(3)如果构造方法为private,那么在其他类中不能创建该类的对象。 
5、抽象类
(1)抽象类不能创建对象。
(2)如果一个类中一个方法为抽象方法,则这个类必须为abstract抽象类。
(3)继承抽象类的类在类中必须实现抽象类中的抽象方法。
(4)抽象类中可以有抽象方法,也可有非抽象方法。抽象方法不能为private。
(5)间接继承抽象类的类可以不给出抽象方法的定义。
6、final关键字
(1)一个对象是常量,不代表不能转变对象的成员,仍可以其成员进行操作。
(2)常量在使用前必须赋值,但除了在声明的同时初始化外,就只能在构造方法中初始化。
(3)final修饰的方法不能被重置(在子类中不能出现同名方法)。
(4)如果声明一个类为final,则所有的方法均为final,无论其是否被final修饰,但数据成员可为final也可不是。
7、接口interface(用implements来实现接口)
(1)接口中的所有数据均为static和final即静态常量。尽管可以不用这两个关键字修饰,但必须给常量赋初值。
(2)接口中的方法均为public,在实现接口类中,实现方法必须可public关键字。
(3)如果使用public来修饰接口,则接口必须与文件名相同。
8、多重继承 
(1)一个类继承了一个类和接口,那么必须将类写在前面,接口写在后面,接口之间用逗号分隔。

(2)接口之间可多重继承,注意使用关键字extends。

(3)一个类虽只实现了一个接口,但不仅要实现这个接口的所有方法,还要实现这个接口继承的接口的方法,接口中的所有方法均须在类中实现。
  
9、接口的嵌入   

(1)接口嵌入类中,可以使用private修饰。此时,接口只能在所在的类中实现,其他类不能访问。  

(2)嵌入接口中的接口一定要为public。   
  
10、类的嵌入   

(1)类可以嵌入另一个类中,但不能嵌入接口中。   
}  
(2)在静态方法或其他方法中,不能直接创建内部类对象,需通过手段来取得。   

手段有两种:  
  
class A { class B {} B getB() { B b = new B(); return b; } } static void m() { A a = new A(); A.B ab = a.getB(); // 或者是 A.B ab = a.new B(); }   
  

(3)一个类继承了另一个类的内部类,因为超类是内部类,而内部类的构造方法不能自动被调用,这样就需要在子类的构造方法中明确的调用超类的构造方法。接上例:  
  
class C extends A.B { C() { new A().super(); // 这一句就实现了对内部类构造方法的调用。 } }  


构造方法也可这样写:

C(A a) { a.super(); } // 使用这个构造方法创建对象,要写成C c = new C(a); a是A的对象。

11、异常类JAVA中除了RunTimeException类,其他异常均须捕获或抛出。

TOP

深入探讨、理解Java的CLASSPATH


从表面上看,Javaclasspath(类路径)很简单,但一直以来它都是一个产生问题和混乱的根源。本文介绍classpath的基本知识、可能产生的问题,并提供了一个简单的classpath管理工具。
和Java类路径(classpath)打交道的过程中,开发者偶尔会遇到麻烦。这是因为,类装载器实际装入的是哪一个类有时并不显而易见,当应用程序的classpath包含大量的类和目录时,情况尤其严重。本文将提供一个工具,它能够显示出被装入类文件的绝对路径名。

一、Classpath基础
Java虚拟机(JVM)借助类装载器装入应用程序使用的类,具体装入哪些类根据当时的需要决定。CLASSPATH环境变量告诉类装载器到哪里去寻找第三方提供的类和用户定义的类。另外,你也可以使用JVM命令行参数-classpath分别为应用程序指定类路径,在-classpath中指定的类路径覆盖CLASSPATH环境变量中指定的值。
类路径中的内容可以是:文件的目录(包含不在包里面的类),包的根目录(包含已打包的类),包含类的档案文件(比如.zip文件或者.jar文件)。在Unix家族的系统上,类路径的各个项目由冒号分隔,在MS Windows系统上,它们由分号分隔。
类装载器以委托层次的形式组织,每一个类装载器有一个父类装载器。当一个类装载器被要求装载某个类时,它在尝试自己寻找类之前会把请求先委托给它的父类装载器。系统类装载器,即由安装在系统上的JDK或JRE提供的默认类装载器,通过CLASSPATH环境变量或者-classpath这个JVM命令行参数装入第三方提供的类或者用户定义的类。系统类装载器委托扩展类装载器装入使用Java Extension机制的类。扩展类装载器委托自举类装载器(bootstrap class loader)装入核心JDK类。
你可以自己开发特殊的类装载器,定制JVM如何动态地装入类。例如,大多数Servlet引擎使用定制的类装载器,动态地装入那些在classpath指定的目录内发生变化的类。
必须特别注意的是(也是令人吃惊的是),类装载器装入类的次序就是类在classpath中出现的次序。类装载器从classpath的第一项开始,依次检查每一个设定的目录和压缩文件,尝试找出待装入的类文件。当类装载器第一次找到具有指定名字的类时,它就把该类装入,classpath中所有余下的项目都被忽略。
看起来很简单,对吧?
二、可能出现的问题
不管他们是否愿意承认,初学者和富有经验的Java开发者都一样,他们都曾经在某些时候(通常是在那些最糟糕的情形下)被冗长、复杂的classpath欺骗。应用程序所依赖的第三方类和用户定义类的数量逐渐增长,classpath也逐渐成了一个堆积所有可能的目录和档案文件名的地方。此时,类装载器首先装载的究竟是哪一个类也就不再显而易见。如果classpath中包含重复的类入口,这个问题尤其突出。前面已经提到,类装载器总是装载第一个它在classpath中找到的具有合适名字的类,从实际效果看,它“隐藏”了其他具有合适名字但在classpath中优先级较低的类。
如果不小心,你很容易掉进这个classpath的陷阱。当你结束了一天漫长的工作,最后为了让应用程序使用最好、最新的类,你把一个目录加入到了classpath,但与此同时,你却忘记了:在classpath的另一个具有更高优先级的目录下,存放着该类的另一个版本!
三、一个简单的classpath工具
优先级问题是扁平路径声明方法与生俱来固有的问题,但它不是只有Java的classpath才有的问题。要解决这个问题,你只需站到富有传奇色彩的软件巨构的肩膀上:Unix操作系统有一个which命令,在命令参数中指定一个名字,which就会显示出当这个名字作为命令执行时执行文件的路径名。实际上,which命令是分析PATH变量,然后找出命令第一次出现的位置。对于Java的类路径管理来说,这应该也是一个好工具。在它的启发之下,我着手设计了一个Java工具JWhich。这个工具要求指定一个Java类的名字,然后根据classpath的指引,找出类装载器即将装载的类所在位置的绝对路径。
下面是一个JWhich的使用实例。它显示出当Java类装载器装载com.clarkware.ejb.ShoppingCartBean类时,该类第一次出现位置的绝对路径名,查找结果显示该类在某个目录下:
> java JWhich com.clarkware.ejb.ShoppingCartBean
Class 'com.clarkware.ejb.ShoppingCartBean' found in '/home/mclark/classes/com/clarkware/ejb/ShoppingCartBean.class'

下面是第二个JWhich的使用实例。它显示出当Java类装载器装载javax.servlet.http.HttpServlet类时,该类第一次出现位置的绝对路径名,查找结果显示该类在某个档案文件中:
> java JWhich javax.servlet.http.HttpServlet
Class 'javax.servlet.http.HttpServlet' found in 'file:/home/mclark/lib/servlet.jar!/javax/servlet/http/HttpServlet.class'

四、JWhich的工作过程
要精确地测定classpath中哪一个类先被装载,你必须深入到类装载器的思考方法。事实上,具体实现的时候并没有听起来这么复杂——你只需直接询问类装载器就可以了!
1: public class JWhich {
2:
3: /**
4: * 根据当前的classpath设置,
5: * 显示出包含指定类的类文件所在
6: * 位置的绝对路径
7: *
8: * @param className <类的名字>
9: */
10: public static void which(String className) {
11:
12: if (!className.startsWith("/")) {
13: className = "/" + className;
14: }
15: className = className.replace('.', '/');
16: className = className + ".class";
17:
18: java.net.URL classUrl =
19: new JWhich().getClass().getResource(className);
20:
21: if (classUrl != null) {
22: System.out.println("\nClass '" + className +
23: "' found in \n'" + classUrl.getFile() + "'");
24: } else {
25: System.out.println("\nClass '" + className +
26: "' not found in \n'" +
27: System.getProperty("java.class.path") + "'");
28: }
29: }
30:
31: public static void main(String args[]) {
32: if (args.length > 0) {
33: JWhich.which(args[0]);
34: } else {
35: System.err.println("Usage: java JWhich");
36: }
37: }
38: }

首先,你必须稍微调整一下类的名字以便类装载器能够接受(12-16行)。在类的名字前面加上一个“/”表示要求类装载器对classpath中的类名字进行逐字精确匹配,而不是尝试隐含地加上调用类的包名字前缀。把所有“.”转换为“/”的目的是,按照类装载器的要求,把类名字格式化成一个合法的URL资源名。
接下来,程序向类装载器查询资源,这个资源的名字必须和经过适当格式化的类名字匹配(18-19行)。每一个Class对象维护着一个对装载它的ClassLoader对象的引用,所以这里是向装载JWhich类的类装载器查询。Class.getResource()方法实际上委托装入该类的类装载器,返回一个用于读取类文件资源的URL;或者,当指定的类名字不能在当前的classpath中找到时,Class.getResource()方法返回null。
最后,如果当前的classpath中能够找到指定的类,则程序显示包含该类的类文件所在位置的绝对路径名(21-24行)。作为一种调试辅助手段,如果当前classpath中不能找到指定的类,则程序获取java.class.path系统属性并显示当前的classpath(24-28行)。
很容易想象,在使用Servlet引擎classpath的Java Servlet中,或者在使用EJB服务器classpath的EJB组件中,上面这段简单的代码是如何运作。例如,如果JWhich类是由Servlet引擎的定制类装载器装入,那么程序将用Servlet引擎的类装载器去寻找指定的类。如果Servlet引擎的类装载器不能找到类文件,它将委托它的父类装载器。一般地,当JWhich被某个类装载器装入时,它能够找出当前类装载器以及所有其父类装载器所装入的所有类。
如果需要是所有发明之母,那么帮助我们管理Java类路径的工具可以说迟到了很长时间。Java新闻组和邮件列表中充塞着许多有关classpath的问题,现在JWhich为我们提供了一个简单却强大的工具,帮助我们在任何环境中彻底玩转Java类路径。

TOP

Java相关:

成为java高手的八大条件

世界上并没有成为高手的捷径,但一些基本原则是可以遵循的。

1、扎实的
基础

  数据结构、离散数学、编译原理,这些是所有计算机科学的基础,如果不掌握它们,很难写出高水平的程序。程序人人都会写,但当你发现写到一定程度很难再提高的时候,就应该想想是不是要回过头来学学这些最基本的理论。不要一开始就去学OOP,即使你再精通OOP,遇到一些基本算法的时候可能也会束手无策。因此多读一些计算机基础理论方面的书籍是非常有必要的。

2、丰富的想像力

  不要拘泥于固定的思维方式,遇到问题的时候要多想几种解决问题的方案,试试别人从没想过的方法。丰富的想像力是建立在丰富的知识的基础上,除计算机以外,多涉猎其他的学科,比如天文、物理、数学等等。开阔的思维对程序员来说很重要。

3、最简单的是最好的

  这也许是所有科学都遵循的一条准则,复杂的质能转换原理在爱因斯坦眼里不过是一个简单得不能再简单的公式:E=mc2。简单的方法更容易被人理解,更容易实现,也更容易维护。遇到问题时要优先考虑最简单的方案,只有简单方案不能满足要求时再考虑复杂的方案。

4、不钻牛角尖

  当你遇到障碍的时候,不妨暂时远离电脑,看看窗外的风景,听听轻音乐,和朋友聊聊天。当我遇到难题的时候会去玩游戏,当负责游戏的那部分大脑细胞极度亢奋的时候,负责编程的那部分大脑细胞就得到了充分的休息。当重新开始工作的时候,我会发现那些难题现在竟然可以迎刃而解。

  5、对答案的渴求

  人类自然科学的发展史就是一个渴求得到答案的过程,即使只能知道答案的一小部分也值得我们去付出。只要你坚定信念,一定要找到问题的答案,你才会付出精力去探索,即使最后没有得到答案,在过程中你也会学到很多东西。

  6、多与别人交流

  三人行必有我师,也许在一次和别人不经意的谈话中,就可以迸出灵感的火花。多上上网,看看别人对同一问题的看法,会给你很大的启发。

  7、良好的编程风格

  注意养成良好的习惯,代码的缩进编排,变量的命名规则要始终保持一致。大家都知道如何排除代码中错误,却往往忽视了对注释的排错。注释是程序的一个重要组成部分,它可以使你的代码更容易理解,而如果代码已经清楚地表达了你的思想,就不必再加注释了,如果注释和代码不一致,那就更加糟糕。

  8、韧性和毅力

  这也许是“高手”和一般程序员最大的区别。高手们并不是天才,他们是在无数个日日夜夜中磨炼出来的。成***能给我们带来无比的喜悦,但过程却是无比的枯燥乏味。你不妨做个测试,找个10000以内的素数表,把它们全都抄下来,然后再检查三遍,如果能够不间断地完成这一工作,你就可以满足这一条。

TOP

classpath   相关

Java虚拟机深入研究

说起Java,人们首先想到的是Java编程语言,然而事实上,Java是一种技术,它由四方面组成:Java编程语言、Java类文件格式、Java虚拟机和Java应用程序接口(Java API)。它们的关系如下图所示:中文JAVA技术网q#[5`+l7L7JS

3xF g,Y"APe"V0

中文JAVA技术网-[/K a k%rU7v[
图1 Java四个方面的关系


%U7p|6bK"Tc0  运行期环境代表着Java平台,开发人员编写Java代码(.java文件),然后将之编译成字节码(.class文件)。最后字节码被装入内存,一旦字节码进入虚拟机,它就会被解释器解释执行,或者是被即时代码发生器有选择的转换成机器码执行。从上图也可以看出Java平台由Java虚拟机和Java应用程序接口搭建,Java语言则是进入这个平台的通道,用Java语言编写并编译的程序可以运行在这个平台上。这个平台的结构如下图所示:中文JAVA技术网O5E%k W7K|!j'{V
中文JAVA技术网Q&Cp5kd6j#Tm


M;{j i$r)j*C0

中文JAVA技术网*nxfdx*[ t{$nW
  在Java平台的结构中, 可以看出,Java虚拟机(JVM) 处在核心的位置,是程序与底层操作系统和硬件无关的关键。它的下方是移植接口,移植接口由两部分组成:适配器和Java操作系统, 其中依赖于平台的部分称为适配器;JVM 通过移植接口在具体的平台和操作系统上实现;在JVM 的上方是Java的基本类库和扩展类库以及它们的API, 利用Java API编写的应用程序(application) 和小程序(Java applet) 可以在任何Java平台上运行而无需考虑底层平台, 就是因为有Java虚拟机(JVM)实现了程序与操作系统的分离,从而实现了Java 的平台无关性。
v,g?`W)K&e n0
F8_!E p0UHzD0  那么到底什么是Java虚拟机(JVM)呢?通常我们谈论JVM时,我们的意思可能是:中文JAVA技术网+u iw4n5S| V!o-S3c^,@

UzCL4G3V0  对JVM规范的的比较抽象的说明;
;e9V8VY&gM#z0  对JVM的具体实现;
XXM*g"j[{qo?X&Z0  在程序运行期间所生成的一个JVM实例。中文JAVA技术网,c-Iy R |5D
中文JAVA技术网0kuS(g7m!`
  对JVM规范的的抽象说明是一些概念的集合,它们已经在书《The Java Virtual Machine Specification》(《Java虚拟机规范》)中被详细地描述了;对JVM的具体实现要么是软件,要么是软件和硬件的组合,它已经被许多生产厂商所实现,并存在于多种平台之上;运行Java程序的任务由JVM的运行期实例单个承担。在本文中我们所讨论的Java虚拟机(JVM)主要针对第三种情况而言。它可以被看成一个想象中的机器,在实际的计算机上通过软件模拟来实现,有自己想象中的硬件,如处理器、堆栈、寄存器等,还有自己相应的指令系统。中文JAVA技术网8I&J R2F;O Qb
中文JAVA技术网9B)vNug
  JVM在它的生存周期中有一个明确的任务,那就是运行Java程序,因此当Java程序启动的时候,就产生JVM的一个实例;当程序运行结束的时候,该实例也跟着消失了。下面我们从JVM的体系结构和它的运行过程这两个方面来对它进行比较深入的研究。
[{NM0? BI0Java虚拟机的体系结构中文JAVA技术网2n!r$@&h-VQ X&g
中文JAVA技术网!C ?[&@QRU8I1J,K
  刚才已经提到,JVM可以由不同的厂商来实现。由于厂商的不同必然导致JVM在实现上的一些不同,然而JVM还是可以实现跨平台的特性,这就要归功于设计JVM时的体系结构了。
VnYn5Y6T S.]0
g gm3d'C8vny0  我们知道,一个JVM实例的行为不光是它自己的事,还涉及到它的子系统、存储区域、数据类型和指令这些部分,它们描述了JVM的一个抽象的内部体系结构,其目的不光规定实现JVM时它内部的体系结构,更重要的是提供了一种方式,用于严格定义实现时的外部行为。每个JVM都有两种机制,一个是装载具有合适名称的类(类或是接口),叫做类装载子系统;另外的一个负责执行包含在已装载的类或接口中的指令,叫做运行引擎。每个JVM又包括方法区、堆、Java栈、程序计数器和本地方法栈这五个部分,这几个部分和类装载机制与运行引擎机制一起组成的体系结构图为:中文JAVA技术网%kW6Zs#bD2Ok

e~&j2Z e0Umc0


}|xUs#[9U e;]0图3 JVM的体系结构中文JAVA技术网 ~u'S6L&Nk

中文JAVA技术网 L]&E;E1l _k p_*j
  JVM的每个实例都有一个它自己的方法域和一个堆,运行于JVM内的所有的线程都共享这些区域;当虚拟机装载类文件的时候,它解析其中的二进制数据所包含的类信息,并把它们放到方法域中;当程序运行的时候,JVM把程序初始化的所有对象置于堆上;而每个线程创建的时候,都会拥有自己的程序计数器和Java栈,其中程序计数器中的值指向下一条即将被执行的指令,线程的Java栈则存储为该线程调用Java方法的状态;本地方法调用的状态被存储在本地方法栈,该方法栈依赖于具体的实现。
}F;WHYdq h5F0中文JAVA技术网5vbh*~A"x"^s8N
  下面分别对这几个部分进行说明。
v2v;i ]C*U ~n)f2w-g0中文JAVA技术网7d%s@0J,K
  执行引擎处于JVM的核心位置,在Java虚拟机规范中,它的行为是由指令集所决定的。尽管对于每条指令,规范很详细地说明了当JVM执行字节码遇到指令时,它的实现应该做什么,但对于怎么做却言之甚少。Java虚拟机支持大约248个字节码。每个字节码执行一种基本的CPU运算,例如,把一个整数加到寄存器,子程序转移等。Java指令集相当于Java程序的汇编语言。
z@p,c e s0中文JAVA技术网w|!kLD
  Java指令集中的指令包含一个单字节的操作符,用于指定要执行的操作,还有0个或多个操作数,提供操作所需的参数或数据。许多指令没有操作数,仅由一个单字节的操作符构成。中文JAVA技术网(h/d6E`DL

f;i&yui+a a S$_9A0  虚拟机的内层循环的执行过程如下:
1U{(r5m9Z*lO [0
+jSB ]Ne,S D0do{
9`$A qd-rp |A0取一个操作符字节;
&sr(@/I!uR0根据操作符的值执行一个动作;中文JAVA技术网'Xg M O-v&{/~
}while(程序未结束)中文JAVA技术网9X Aip_$hT

f#xw2Fiw'x0  由于指令系统的简单性,使得虚拟机执行的过程十分简单,从而有利于提高执行的效率。指令中操作数的数量和大小是由操作符决定的。如果操作数比一个字节大,那么它存储的顺序是高位字节优先。例如,一个16位的参数存放时占用两个字节,其值为:
_%Dmp!|0
9I4x6o-X"j0  第一个字节*256+第二个字节字节码。中文JAVA技术网rWS*Xz9L

h+Oi#H9\s/B0  指令流一般只是字节对齐的。指令tableswitch和lookup是例外,在这两条指令内部要求强制的4字节边界对齐。
sbd*E#cgJ0
Zp}(H T{0  对于本地方法接口,实现JVM并不要求一定要有它的支持,甚至可以完全没有。Sun公司实现Java本地接口(JNI)是出于可移植性的考虑,当然我们也可以设计出其它的本地接口来代替Sun公司的JNI。但是这些设计与实现是比较复杂的事情,需要确保垃圾回收器不会将那些正在被本地方法调用的对象释放掉。中文JAVA技术网:B&fMn Ms

3B Mg%p ^_oe(Q0  Java的堆是一个运行时数据区,类的实例(对象)从中分配空间,它的管理是由垃圾回收来负责的:不给程序员显式释放对象的能力。Java不规定具体使用的垃圾回收算法,可以根据系统的需求使用各种各样的算法。
Ug5Q0zdS%j9pdE0
G7Q l xyS0  Java方法区与传统语言中的编译后代码或是Unix进程中的正文段类似。它保存方法代码(编译后的java代码)和符号表。在当前的Java实现中,方法代码不包括在垃圾回收堆中,但计划在将来的版本中实现。每个类文件包含了一个Java类或一个Java界面的编译后的代码。可以说类文件是Java语言的执行代码文件。为了保证类文件的平台无关性,Java虚拟机规范中对类文件的格式也作了详细的说明。其具体细节请参考Sun公司的Java虚拟机规范。
g P4l7D`q0中文JAVA技术网,a4Pe2m|n+n;`
  Java虚拟机的寄存器用于保存机器的运行状态,与微处理器中的某些专用寄存器类似。Java虚拟机的寄存器有四种:
\|6H5n P$c Na0中文JAVA技术网 E R)XW&kb,QS5r(tC
  pc: Java程序计数器;中文JAVA技术网)II$d%wK
  optop: 指向操作数栈顶端的指针;中文JAVA技术网6bBw y!z1XWP8C
  frame. 指向当前执行方法的执行环境的指针;。中文JAVA技术网(f/eL8F"_q A}
  vars: 指向当前执行方法的局部变量区第一个变量的指针。
+Y ~3Mk X@2G3X-wD0
qi@W!vv+V0  在上述体系结构图中,我们所说的是第一种,即程序计数器,每个线程一旦被创建就拥有了自己的程序计数器。当线程执行Java方法的时候,它包含该线程正在被执行的指令的地址。但是若线程执行的是一个本地的方法,那么程序计数器的值就不会被定义。
~y)\FTUAY0
5K [w5}n0  Java虚拟机的栈有三个区域:局部变量区、运行环境区、操作数区。
-IQX\pb{+@G v0中文JAVA技术网.ci`W1g!@+X#_'[C
  局部变量区
1G6uWn ^.p g0
$A r4jn)`D/x2xm0  每个Java方法使用一个固定大小的局部变量集。它们按照与vars寄存器的字偏移量来寻址。局部变量都是32位的。长整数和双精度浮点数占据了两个局部变量的空间,却按照第一个局部变量的索引来寻址。(例如,一个具有索引n的局部变量,如果是一个双精度浮点数,那么它实际占据了索引n和n+1所代表的存储空间)虚拟机规范并不要求在局部变量中的64位的值是64位对齐的。虚拟机提供了把局部变量中的值装载到操作数栈的指令,也提供了把操作数栈中的值写入局部变量的指令。
^ [C _ __0X|0
;Cia\ gf+I"QW0  运行环境区中文JAVA技术网+{-i9|-b#F]qU9U

qU#rN](Q0  在运行环境中包含的信息用于动态链接,正常的方法返回以及异常捕捉。中文JAVA技术网 }O3l b!VQC*U

IZw1OM0  动态链接
-Ck0Q)D?6rh6LJ8?"T0中文JAVA技术网ZG*i.uA
  运行环境包括对指向当前类和当前方法的解释器符号表的指针,用于支持方法代码的动态链接。方法的class文件代码在引用要调用的方法和要访问的变量时使用符号。动态链接把符号形式的方法调用翻译成实际方法调用,装载必要的类以解释还没有定义的符号,并把变量访问翻译成与这些变量运行时的存储结构相应的偏移地址。动态链接方法和变量使得方法中使用的其它类的变化不会影响到本程序的代码。中文JAVA技术网_ AS'@"^+\ _(Z
中文JAVA技术网3Fm:GmJ2t,^GC
  正常的方法返回
}UIy6?*d0
*lH/Nq,mWs0  如果当前方法正常地结束了,在执行了一条具有正确类型的返回指令时,调用的方法会得到一个返回值。执行环境在正常返回的情况下用于恢复调用者的寄存器,并把调用者的程序计数器增加一个恰当的数值,以跳过已执行过的方法调用指令,然后在调用者的执行环境中继续执行下去。
F{{c j?Q!d @y(S:r/a0中文JAVA技术网9Etq_4[KQ
  异常捕捉中文JAVA技术网 o7R8\#U|9[Y

?'m'n,QWLT5s*Q5d0  异常情况在Java中被称作Error(错误)或Exception(异常),是Throwable类的子类,在程序中的原因是:①动态链接错,如无法找到所需的class文件。②运行时错,如对一个空指针的引用。程序使用了throw语句。
BQUug0
:GCB5oso+~0  当异常发生时,Java虚拟机采取如下措施:
[*g1b@]0
,EU[VzD:nA0  检查与当前方法相联系的catch子句表。每个catch子句包含其有效指令范围,能够处理的异常类型,以及处理异常的代码块地址。
"r7o F.q#w.q&x-lG_0中文JAVA技术网R ual~L
  与异常相匹配的catch子句应该符合下面的条件:造成异常的指令在其指令范围之内,发生的异常类型是其能处理的异常类型的子类型。如果找到了匹配的catch子句,那么系统转移到指定的异常处理块处执行;如果没有找到异常处理块,重复寻找匹配的catch子句的过程,直到当前方法的所有嵌套的catch子句都被检查过。
:^ x o4Nt!jL0中文JAVA技术网[Be7mj%MXo
  由于虚拟机从第一个匹配的catch子句处继续执行,所以catch子句表中的顺序是很重要的。因为Java代码是结构化的,因此总可以把某个方法的所有的异常处理器都按序排列到一个表中,对任意可能的程序计数器的值,都可以用线性的顺序找到合适的异常处理块,以处理在该程序计数器值下发生的异常情况。
l1`E%KuK]7F6D0
K%MU!o;_x(~2v0r9l0  如果找不到匹配的catch子句,那么当前方法得到一个"未截获异常"的结果并返回到当前方法的调用者,好像异常刚刚在其调用者中发生一样。如果在调用者中仍然没有找到相应的异常处理块,那么这种错误将被传播下去。如果错误被传播到最顶层,那么系统将调用一个缺省的异常处理块。
/W }0f,vY%b},^gC0中文JAVA技术网O gM2` @"|
  操作数栈区中文JAVA技术网 VluL,D[

!X_X0So*WaYQ0  机器指令只从操作数栈中取操作数,对它们进行操作,并把结果返回到栈中。选择栈结构的原因是:在只有少量寄存器或非通用寄存器的机器(如Intel486)上,也能够高效地模拟虚拟机的行为。操作数栈是32位的。它用于给方法传递参数,并从方法接收结果,也用于支持操作的参数,并保存操作的结果。例如,iadd指令将两个整数相加。相加的两个整数应该是操作数栈顶的两个字。这两个字是由先前的指令压进堆栈的。这两个整数将从堆栈弹出、相加,并把结果压回到操作数栈中。
7W*I-bU(L$E6F0中文JAVA技术网Y5G8lA'd$Gy
  每个原始数据类型都有专门的指令对它们进行必须的操作。每个操作数在栈中需要一个存储位置,除了long和double型,它们需要两个位置。操作数只能被适用于其类型的操作符所操作。例如,压入两个int类型的数,如果把它们当作是一个long类型的数则是非法的。在Sun的虚拟机实现中,这个限制由字节码验证器强制实行。但是,有少数操作(操作符dupe和swap),用于对运行时数据区进行操作时是不考虑类型的。
T3B*U{9^0中文JAVA技术网]@k!_g:kKm
  本地方法栈,当一个线程调用本地方法时,它就不再受到虚拟机关于结构和安全限制方面的约束,它既可以访问虚拟机的运行期数据区,也可以使用本地处理器以及任何类型的栈。例如,本地栈是一个C语言的栈,那么当C程序调用C函数时,函数的参数以某种顺序被压入栈,结果则返回给调用函数。在实现Java虚拟机时,本地方法接口使用的是C语言的模型栈,那么它的本地方法栈的调度与使用则完全与C语言的栈相同。中文JAVA技术网3V{S)I&m2|1B Fw_
Java虚拟机的运行过程中文JAVA技术网/b[:R*I EuW
中文JAVA技术网;ST&jxe}
  上面对虚拟机的各个部分进行了比较详细的说明,下面通过一个具体的例子来分析它的运行过程。中文JAVA技术网HJ$H@(R;CV
中文JAVA技术网8h$y8q2O)s+u K
  虚拟机通过调用某个指定类的方法main启动,传递给main一个字符串数组参数,使指定的类被装载,同时链接该类所使用的其它的类型,并且初始化它们。例如对于程序:
8N0EE9T@ x-Ar_0中文JAVA技术网lS[!vZ xj
class HelloApp
:l{S;\(UA5Q,zf0{
'T+_wH-I5B2ec0 public static void main(String[] args)
0L:J tnf4t0 {
phELR Q'b-HfQ)n0  System.out.println("Hello World!";中文JAVA技术网3P!^*y)QbE7Q\
  for (int i = 0; i < args.length; i++ )中文JAVA技术网s/`zwZ!w5pK0?8E
  {中文JAVA技术网TQU'f}l\B
   System.out.println(args);
Y HX'C5~'lg2M0  }
i)k#ETisovp0 }
5VH] K2iRi0}
中文JAVA技术网 _/Z9U$q@*h&q!g"`C
  编译后在命令行模式下键入: java HelloApp run virtual machine
/iiR-\/`eC:Ej0中文JAVA技术网z Ka"Qm:C
  将通过调用HelloApp的方法main来启动java虚拟机,传递给main一个包含三个字符串"run"、"virtual"、"machine"的数组。现在我们略述虚拟机在执行HelloApp时可能采取的步骤。中文JAVA技术网 m6hPx5]W
中文JAVA技术网UAy(j.q
  开始试图执行类HelloApp的main方法,发现该类并没有被装载,也就是说虚拟机当前不包含该类的二进制代表,于是虚拟机使用ClassLoader试图寻找这样的二进制代表。如果这个进程失败,则抛出一个异常。类被装载后同时在main方法被调用之前,必须对类HelloApp与其它类型进行链接然后初始化。链接包含三个阶段:检验,准备和解析。检验检查被装载的主类的符号和语义,准备则创建类或接口的静态域以及把这些域初始化为标准的默认值,解析负责检查主类对其它类或接口的符号引用,在这一步它是可选的。类的初始化是对类中声明的静态初始化函数和静态域的初始化构造方法的执行。一个类在初始化之前它的父类必须被初始化。整个过程如下:中文JAVA技术网y!ng,W lu3_ t
中文JAVA技术网aF#a-ezgb? N

中文JAVA技术网 ?x,L eJcm
图4:虚拟机的运行过程
c&Aiy&B'V-t V3?P6t0

  结束语中文JAVA技术网 I${(XXK2`)l u

WJW4xYN0  本文通过对JVM的体系结构的深入研究以及一个Java程序执行时虚拟机的运行过程的详细分析,意在剖析清楚Java虚拟机的机理。
5z)yn(X6`QJ D o0

TOP

用户    相关:
弹射座椅拉杆——人的错误还是软件的错误?
今天看了VB之父艾兰·库伯几年前写的《软件开发的创新思维》,发现这的确是一本绝妙的书。尽管当时库伯提出的许多观点现在都被普遍接受并认可了,但是,并不是说明所有的问题都解决了。正如软件工程一样,很多人现在提“网络时代的软件工程”,畅想并实践Web2.0时代软件开发的模式,但并不能将曾经已有的软件工程的理论抛弃。可以说,计算机世界里的所有事情都是这样,新的亮点出现了,但并不能说旧有的东西都可以被扔掉。大多数从前的问题到今天仍然作为问题存在着。
VB带给了人们一种新的编程体验。可以说,VB教会了人们如何在编程中注入乐趣。当所有其他人还在命令行或文本编辑器中敲来敲去时,VB程序员已经在拖拽中享受着快速开发的快乐了。它使得那些编程基础并不怎么好的程序员也能够开发出漂亮的程序,起码“可以使用”的程序,降低了软件开发的门槛。在《软件开发的创新思维》这本书中,库伯跳出技术的视角,带领人们从根本上思考人类与机器的关系——在这样一种独特的视角的带领下,你会发现,许多你已经习以为常的行为是多么的荒唐可笑:
对于许多高新技术带来的问题,我们总是倾向于归咎于自己,而从来不曾想过这些技术本身究竟有没有存在问题。在越来越多令人眩晕的技术面前,人们已经进入了自己营造的牢笼。
软件是这样被使用的:软件开发者们先训练自己来适应自己亲手打造的系统(或者是更多则是另外一种可能,训练自己开发的系统以适应自身),并迷恋于这个系统拥有的强大功能,然后写上厚厚的用户手册将自己训练的成果复制给软件使用者。大部分软件开发者都具有“自恋”倾向,他们总是希望用户按照他们的设想来进行操作,对于他们自己,由于习惯于以接受挑战为乐趣,很可能将这种习惯反应到用户界面上来。。。然后在他们眼里,只有不懂软件的用户,没有不懂用户的软件。。。
正好我刚刚自始至终做完一个软件,对此深有体会。作为开发者,我们总是在跟测试人员打交道的时候占据上风,无论是口头还是内心。最习惯的想法是,“没了我们,什么也得不到,你们的工作可以忽略不计。”、“这些测试人员基本上智商等于0,怎么傻到做那样的动作!”、“烦不烦,嘴里蹦出几个字要让我的工作拖延一个星期!天哪,我下辈子绝对不做开发者!”那时认为自己义正词严,但在看这本书时,才意识到一个开发者端正自己的心态是多么的困难。
在这本书对于现有软件的描述中,“弹射座椅拉杆”的说法让我忍俊不禁。“弹射座椅拉杆”指的是在发生紧急情况时,将飞行员弹出座舱的设施。这里指的是当无辜而又可怜的用户使用软件时,猝不及防的被软件踢出门外。用户们必须小心翼翼的使用软件,生怕自己在未来的行为里被软件所嗤笑。只要偶然的触发了“弹射式座椅拉杆”,就会开始一个针对个人的难看插曲,就像是在办公室里忘记穿自己的裤子那样狼狈。。。
正好又跟我做的项目绝妙的对应!在我刚刚参与的项目里,曾经没有区分Error和Warning的弹出信息,结果只要用户稍有不慎,一个大大的红叉再加上一声刺耳的系统“咚”声便会从计算机里蹦出来。天哪!就连我们自己去用都像在看恐怖电影一样惶恐不安,更别说只懂得业务的用户了。好像我们的开发人员天生要履行教育家的职责,要用严刑峻法驯服用户。开发软件的目的从帮助用户做更多的事情转变为驯服用户从而使软件能够无故障的运行。。。根本的错位。。。
其实现在有很多这样的现象,如果一个公司员工由于一个不慎的操作(系统也没有给予足够明确的提示)将该公司的数据库破坏。。。这个员工的命运是可想而知的。。。
人的错误还是软件的错误?起码作为软件开发者来说,应该将大部分问题归结为软件的错误,以此来勉励自己。

TOP

JDK  相关:
JDK1.6(Update3)
文件大小: 38.63 MB 文件版本: V1.0 开发商: Sun 文件来源: 本地 界面语言: 简体中文 授权方式: 免费 运行平台: Windows/Linux Windows x64 Platform - Java(TM) SE Development Kit 6 Update 3

简化Web Services
Mustang 将 简化Web services 的开发和发布. XML和Web服务一直都是Mustang的关注重点.. Mustang为此引入了JAX-WS(Java Architecture for XML-Web Services) 2.0 以及JAXB (Java Architecture for XML Binding) 2.0.. 同时还有Streaming API for XML  (STaX), 它提供了一个双向API,这个API可以通过一个事件流来读取或者写入XML,其中包括跳过某个部分,然后直接关注与文档中的另外一个小部分的能力。


Scripting,整合脚本语言
目前来讲,Java 开发者们必须在Java之外独立地额外编码来使用non-Java 脚本语言。这个头痛的问题将被Mustang 消灭,开发者将更加轻松的使用Perl、PHP、Python、JavaScript 和Ruby等脚本语言。新的框架将允许人们操作任意的脚本语言,和使用Java 对象。

Java SE6中实现了JSR223。这是一个脚本框架,提供了让脚本语言来访问Java内部的方法。你可以在运行的时候找到脚本引擎,然后调用这个引擎去执行脚本。这个脚本API允许你为脚本语言提供Java支持。另外,Web Scripting Framework允许脚本代码在任何的 Servlet容器(例如Tomcat)中生成Web内容。

Database,绑定Derby
开源嵌入式数据库 Derby(JavaDB) 绑定在JDK 1.6中.具体可以参考:JDK 1.6 将绑定开源数据库 Derby

更丰富的Desktop APIs
Mustang中拥有更多强的桌面API提供给开发者, 开发者可以更简单地开发更强大的桌面应用, 比如启动界面的支持,系统托盘的支持,JTable排序等等

监视和管理
Java SE 6中对内存泄漏增强了分析以及诊断能力。当遇到java.lang.OutOfMemory异常的时候,可以得到一个完整的堆栈信息,并且当堆已经满了的时候,会产生一个Log文件来记录这个致命错误。另外,JVM还添加了一个选项,允许你在堆满的时候运行脚本。(这也就是提供了另外一种方法来诊断错误)

增强的JMX 监视API在MBean的属性值传入了一个特定的参数的时候,允许这个应用程序发送一个事件通告。(这里的属性值可以在很复杂的类型中)

对于Solaris 10的用户,为Solaris提供的Hotspot JVM中,提供了一种通过Solaris DTrace(这是个系统的调试工具)来追踪显示JVM内部的活动情况,包括垃圾收集,类装载,线程,锁等等。

Pluggable Annotations
从Java SE 5  带来得新特性Annotations,将在Mustang继续扮演重要角色..

Compiler API:访问编译
对于Java开发工具, 或者Web框架 等的开发者来说, 利用编译器编译动态生成的代码, 是一个普遍的需求.

Mustang实现了JSR 199,  提供了Java编译器API(应用程序接口),允许你从一个Java应用程序中去编译其他的Java源程序--比如在应用程序中动态生成的一些源代码..

Security:安全性
Java SE 6的安全部分,增加了 XML-Digital Signature (XML-DSIG) APIs, 整合了GSS/Kerberos的操作API,LDAP上的JAAS认证。
....

由于相关下载太大无法上传请大家谅解



TOP

基础    开发     相关:

JAVA2核心技术卷I:基础知识(原书第7版)
  • 出版社:机械工业出版
  • 原作者::(美)霍斯特曼(Horstmann,C.S.),(美)科奈尔(Cornell,G.) 著
  • 译作者:叶乃文 等译
  • 价格: 59.84
  • 简介:本书是Java技术经典参考书,多年畅销不衰,第7版在保留以前版本风格的基础上,涵盖Java2开发平台标准版J2SE5.0的基础知识,主要内容包括面各对象程序设计、反射与代理、接口与内部类、事件监听器模型、使用Swing UI工具箱进行图形用户界面设计,异常处理、流输入/输出和对象序列化、
Java编程思想(第4版)

  • 出版社:机械工业出版社
  • 原作者:(美)埃克尔
  • 译作者:陈昊鹏
  • 价格: 108
  • 简介: 内容提要
    本书赢得了全球程序员的广泛赞誉,即使是最晦涩的概念,在Bruce Eckel的文字亲和力和小而直接的编程示例面前也会化解于无形。从Java的基础语法到最高级特性(深入的面向对象概念、多线程、自动项目构建、单元测试和调试等),本书都能逐步指导你轻松掌握
    从本书获得的各项大奖以及来自世界各地的读者评论中,不难看出这是一本经典之作。本书的作者拥有多年教学经验,对C、C++以及Java语言都有独到、深入的见解,以通俗易懂及小而直接的示例解释了一个个晦涩抽象的概念。本书共22章,包括操作符、控制执行流程、访问权限控制、复用类、多态、接口、通过异常处理错误、字符串、泛型、数组、容器深入研究、Java I/O系统、枚举类型、并发以及图形化用户界面等内容。这些丰富的内容,包含了Java语言基础语法以及高级特性,适合各个层次的Java程序员阅读,同时也是高等院校讲授面向对象程序设计语言以及Java语言的绝佳教材和参考书。
    第4版特点:
    适合初学者与专业人员的经典的面向对象叙述方式,为更新的Java SE5/6增加了新的示例和章节。
     测验框架显示程序输出。
    设计模式贯穿于众多示例中:适配器、桥接器、职责链、命令、装饰器、外观、工厂方法、享元、点名、数据传输对象、空对象、代理、单例、状态、策略、模板方法以及访问者。
     为数据传输引入了XML,为用户界面引入了SWT和Flash。
     重新撰写了有关并发的章节,有助于读者掌握线程的相关知识。
     专门为第4版以及Java SE5/6重写了700多个编译文件中的500多个程序。
     支持网站包含了所有源代码、带注解的解决方案指南、网络日志以及多媒体学习资料。
     覆盖了所有基础知识,同时论述了高级特性。
     详细地阐述了面向对象原理。
     在线可获得Java讲座CD,其中包含Bruce Eckel的全部多媒体讲座。
    www.MindView.net网站上可以观看现场讲座、咨询和评论。
    专门为第4版以及Java SE5/6重写了700多个编译文件中的500多个程序。
    支持网站包含了所有源代码、带注解的解决方案指南、网络日志以及多媒体学习资料。
    覆盖了所有基础知识,同时论述了高级特性。
    详细地阐述了面向对象原理。
    在线可获得Java讲座CD,其中包含Bruce Eckel的全部多媒体讲座。
    www.MindView.net网站上可以观看现场讲座、咨询和评论。

    作者简介
    Bruce Eckel是MindView公司(www.MindView.net)的总裁,该公司向客户提供软件咨询和培训。他是C++标准委员会拥有表决权的成员之一,拥有应用物理学学士和计算机工程硕士学位。除本书外,他还是《C++编程思想》的作者,并与人合著了《C++编程思想 第2卷》(这两本书的英文影印版及中文版均已由机械工业出版社引进出版)及其他著作。他已经发表了150多篇论文,还经常参加世界各地的研讨会并进行演讲。

    编辑推荐
    ★全球程序员必备图书《Java编程思想》的最新版本!
      获奖历史:•2003年《Software Development》杂志最佳书籍Jolt大奖
      •2003年《Java Developer’s Journal》读者选择最佳书籍奖
      •2001年《Java World》编辑选择最佳书籍奖
      •2000年《Java World》读者选择最佳书籍奖
      •1999年《Software Development》杂志最佳产品奖
      •1998年《Java Developer’s Journal》编辑选择最佳书籍奖

    目录
    读者评论
    前言
    简介
    第1章 对象导论
    1.1 抽象过程
    1.2 每个对象都有一个接口
    1.3 每个对象都提供服务
    1.4 被隐藏的具体实现
    1.5 复用具体实现
    1.6 继承
    1.6.1 “是一个”(is-a)与“像是一个”(is-like-a)关系
    1.7 伴随多态的可互换对象
    1.8 单根继承结构
    1.9 容器
    1.9.1 参数化类型(范型)
    1.10 对象的创建和生命期
    1.11 异常处理:处理错误
    1.12 并发编程
    1.13 Java与Internet
    1.13.1 Web是什么
    1.13.2 客户端编程
    1.13.3 服务器端编程
    1.22 总结
    第2章 一切都是对象
    2.1 用引用操纵对象
    2.2 必须由你创建所有对象
    2.2.1 存储到什么地方
    2.2.2 特例:基本类型
    2.2.3 Java中的数组
    2.3 永远不需要销毁对象
    2.3.1 作用域
    2.3.2 对象的作用域
    2.4 创建新的数据类型:类
    2.4.1 域和方法
    2.4.2 基本成员默认值
    2.5 方法、参数和返回值
    2.5.1 参数列表
    2.6 构建一个Java程序
    2.6.1 名字可见性
    2.6.2 运用其他构件
    2.6.3 static 关键字
    2.7 你的第一个Java程序
    编译和运行
    2.8 注释和嵌入式文档
    2.8.1 注释文档
    2.8.2 语法
    2.8.3 嵌入式HTML
    2.8.4 一些标签示例
    2.8.5 文档示例
    2.9 编码风格
    2.10 总结
    2.11 练习
    第3章 操作符
    3.1 更简单的打印语句
    3.2 使用Java操作符
    3.3 优先级
    3.4 赋值
    3.4.1 方法调用中的别名问题
    3.5 算术操作符
    3.5.1 一元加、减操作符
    3.6 自动递增和递减
    3.7 关系操作符
    3.7.1 测试对象的等价性
    3.8 逻辑操作符
    3.8.1 短路
    3.9 直接常量
    3.9.1 指数记数法
    3.10 按位操作符
    3.11 移位操作符
    3.12 三元操作符 if-else
    3.13 字符串操作符 + 和 +=
    3.14 使用操作符时常犯的错误
    3.15 类型转换操作符
    3.15.1 截尾和舍入
    3.15.2提升
    3.16 Java没有“sizeof”
    3.17 操作符小结
    3.18 总结
    第4章 控制执行流程
    4.1 true和false
    4.2 if-else
    4.3 迭代
    4.3.1 do-while
    4.3.2 for
    4.3.3 逗号操作符
    4.4 Foreach语法
    4.5 return
    4.6 break和 continue
    4.7 臭名昭著的“goto”
    4.8 switch
    4.9 总结
    第5章 初始化与清理
    5.1 用构造器确保初始化
    5.2 方法重载
    5.2.1 区分重载方法
    5.2.2 涉及基本类型的重载
    5.2.3 以返回值区分重载方法
    5.3 缺省构造器
    5.4 this关键字
    5.4.1 在构造器中调用构造器
    5.4.2 static的含义
    5.5 清理:终结处理和垃圾回收
    5.5.1 finalize()的用途何在
    5.5.2 你必须实施清理
    5.5.3 终结条件
    5.5.4 垃圾回收器如何工作
    5.6 成员初始化
    5.6.1 指定初始化
    5.7 构造器初始化
    5.7.1 初始化顺序
    5.7.2. 静态数据的初始化
    5.7.3. 显式的静态初始化
    5.7.4. 非静态实例初始化
    5.8 数组初始化
    5.8.1 可变参数列表
    5.9 枚举类型
    5.10 总结
    第6章 访问权限控制
    第7章 复用类
    第8章 多态
    第9章 接口
    第10章 内部类
    第11章 持有对象
    第12章 通过异常处理错误
    第13章 字符串
    第14章 类型信息
    第15章 泛型
    第16章 数组
    第17章 容器深入研究
    第18章 Java I/O系统
    第19章 枚举类型
    第20章 注解
    第21章 并发
    第22章 图形化用户界面
    附录A 补充材料
    可下载的补充材料
    Thinking in C:Java的基础
    Java编程思想 研讨课
    Hands-on Java研讨课CD
    Thinking in Objects研讨课
    Thinking in Enterprise Java
    Thinking in Patterns(with Java)
    Thinking in Patterns研讨课
    设计咨询与复审
    附录B 资源
    软件
    编辑器与IDE
    书籍
    分析与设计
    Python
    我的著作列表
    索引


    媒体评论
    我见过的最好的Java书!您做了一项了不起的工作。您的深度令人赞叹,出版的时候,我一定会购买一本。我从1996年10月就开始学习Java,其间也读过好几本这方面的书,但我觉得您这本才是“必读书”。最近几个月,我一直集中精力于一个完全用Java开发的产品。您的书帮我夯实了某些不牢固的知识点,并拓展了我的知识面。我甚至在面试签约者时引用书中的内容,作为参考的依据。通过问一些我从书中学到的知识,来判断他们对Java的理解程度(例如,数组与Vector的区别)。您的书真是伟大!
    Steve Wilkinson, 资深专家, MCI 电信公司
    每个Java程序员都应该反复研读《Think in Java》,并且随身携带以便随时参考。书中的练习颇具挑战性,而有关集合的章节已臻化境!本书不仅帮助我通过了Sun Certified Java Programmer考试,而且它还是我遇到Java问题时,求助的首选书籍。
                       ——Jim Pleger, Loudoun郡(弗吉尼亚)政府
    这本书比我见过的所有Java书都要好得多。循序渐进……非常完整,并搭配恰到好处的范例,睿智而不呆板的解说……这使本书的品质比别的书“超出了一个数量级”。与其他Java书相比,我发现本书考虑非常周全、前后一致、理性坦诚、文笔流畅、用词准确。恕我直言,这是一本学习Java的理想书籍。
                       ——Anatoly Vorobey, 以色列海法Technion大学
    在我所见过的程序设计指南中(无论何种语言),这绝对是最好的一本。
                       ——Joakim Ziegler, FIX系统管理员
    感谢您这本精彩的、令人愉快的Java书。
                       ——Dr. Gavin Pillay, 登记员, 南非爱德华八世医院
    再次感谢您这本杰出的书。作为一名不用C语言的程序员,我曾经感到(学习Java)步履维艰,但是您的书让我一目了然。能够一开始就理解底层的概念和原理,而不是通过反复试验来自己建立概念模型,真是太棒了。我希望能在不久的将来参加您的讨论课。
                       ——Randall R. Hawley, 自动化工程师, Eli Lilly公司
    我见过的计算机著作中,这是最好的一本。
                       ——Tom Holland
    这是我读过的编程语言书中最棒的一本……有关Java的书中最棒的一本。
                       ——Ravindra Pai, Oracle 公司, SUNOS 产品线部门
    我见过的最好的Java书!您做了一项了不起的工作。您的深度令人赞叹,出版的时候,我一定会购买一本。我从1996年10月就开始学习Java,其间也读过好几本这方面的书,但我觉得您这本才是“必读书”。最近几个月,我一直集中精力于一个完全用Java开发的产品。您的书帮我夯实了某些不牢固的知识点,并拓展了我的知识面。我甚至在面试签约者时引用书中的内容,作为参考的依据。通过问一些我从书中学到的知识,来判断他们对Java的理解程度(例如,数组与Vector的区别)。您的书真是伟大!
                       ——Steve Wilkinson, 资深专家, MCI 电信公司
    伟大的书。迄今为止我见过的最佳Java书籍。
                       ——Jeff Sinclair, 软件工程师, Kestral 计算技术公司
    感谢您的《Thinking in Java》。早就应该有人把仅仅介绍语言的教程编写成富有思想、分析透彻的入门指南,而不是局限于“某个公司”的语言。我阅读过许多这方面的书,但只有您和Patrick Winston的作品给我印象深刻。我已经向客户推荐这本书。再次谢谢您。
                       ——Richard Brooks, Java 咨询顾问, 达拉斯Sun专业服务部门
    Bruce,您的书真是太棒了!您的讲解清晰明确。通过这本迷人的书,我获得了大量Java知识。练习题也同样令人着迷,它们对巩固各章阐述的知识起到了很好的效果。我期待您的更多作品。对您的这本著作致以谢意。阅读了《Thinking in Java》之后,我的代码质量大有改善。为此我要感激您,我相信,维护我的代码的程序员同样也会感激您。
                       ——Yvonne Watkins, Discover 技术公司

TOP

JAVA中具有实例缓存的不可变类

不可变类的实例的状态不会变化,这样的实例可以安全地被其他与之关联的对象共享,还可以安全地被多个线程共享。为了节省内存空间,优化程序的性能,应该尽可能地重用不可变类的实例,避免重复创建具有相同属性值的不可变类的实例。JDK 1.5的基本类库中,对一些不可变类,如Integer类做了优化,它具有一个实例缓存,用来存放程序中经常使用的Integer实例。JDK 1.5的Integer类新增了一个参数,为int类型的静态工厂方法valueOf(int i),它的处理流程如下:
if(在实例缓存中存在取值为i的实例)
   
直接返回这个实