区分overloading:
每个overloading的方法都必须采用独一无二的自变量类型列表
自变量的顺序也足够我们区分两个方法(尽管我们通常不愿意采用这种方法,因为它会产生难以维护的代码)
// promotion of primitives and overloading // 若我们的数据类型“小于”方法中使用的自变量,就会对那种数据类型进行“转型”处理。 // char 获得的效果稍有些不同,这是由于假期它没有发现一个准确的char 匹配,就会转型为int。 public class PrimitiveOverloading { // boolean can't be automatically converted static void prt(String s){ System.out.println(s); } void f1(char x){prt("f1(char)");} void f1(byte x){prt("f1(byte)");} void f1(short x){prt("f1(short)");} void f1(int x){prt("f1(int)");} void f1(long x){prt("f1(long)");} void f1(float x){prt("f1(float)");} void f1(double x){prt("f1(double)");} void f2(byte x){prt("f2(byte)");} void f2(short x){prt("f2(short)");} void f2(int x){prt("f2(int)");} void f2(long x){prt("f2(long)");} void f2(float x){prt("f2(float)");} void f2(double x){prt("f2(double)");} void f3(short x){prt("f3(short)");} void f3(int x){prt("f3(int)");} void f3(long x){prt("f3(long)");} void f3(float x){prt("f3(float)");} void f3(double x){prt("f3(double)");} void f4(int x){prt("f4(int)");} void f4(long x){prt("f4(long)");} void f4(float x){prt("f4(float)");} void f4(double x){prt("f4(double)");} void f5(long x){prt("f5(long)");} void f5(float x){prt("f5(float)");} void f5(double x){prt("f5(double)");} void f6(float x){prt("f6(float)");} void f6(double x){prt("f6(double)");} void f7(double x){prt("f7(double)");} void testConstVal(){ prt("Testing with 5"); f1(5);f2(5);f3(5);f4(5);f5(5);f6(5);f7(5); } void testChar(){ char x = 'X'; prt("char argument:"); f1(x);f2(x);f3(x);f4(x);f5(x);f6(x);f7(x); } public static void main(String[] args) { PrimitiveOverloading p = new PrimitiveOverloading(); p.testConstVal(); p.testChar(); } } /* Testing with 5 f1(int) f2(int) f3(int) f4(int) f5(long) f6(float) f7(double) char argument: f1(char) f2(int) f3(int) f4(int) f5(long) f6(float) f7(double) */
我们可能调用一个方法,同时忽略返回值 - 则返回值Overloading就会有问题。- 为它的副作用去调用一个方法。
class Banana { void f(int i) { /* ... */ } } Banana a = new Banana(), b = new Banana(); a.f(1); b.f(2);若只有一个名叫f()的方法,怎样才能知道自己是a还是为b调用的呢?
为了能用简便的、面向对象的语法来书写代码 - 亦即“将消息发给对象”,编译器为我们完成了一些幕后工作。
其中一个秘密就是第一自变量传递给方法f(),而且那个自变量是准备操作的那个对象的句柄。
Banana.f(a,1); Banana.f(b,2);这是内部的表达形式,我们并不能这样书写表达式,并试图让编译器接受它。但是,通过它可理解幕后到底
发生了什么事情。
在构造器里调用构造器
若为一个类写多个构造器,那么经常都需要在一个构造器里面调用另一个构造器,以避免写重复的代码。
可用this关键字做到这一点。
尽管可用this调用一个构造器,但不可调用两个。
构造器调用必须是我们做的第一件事情,否则会收到编译程序的报错信息。
假定我们的对象分配了一个“特殊”内存区域,没有使用new。垃圾收集器只知道释放那些由new分配的内存,所以不知道如何释放对象的“特殊”内存。为解决这个问题,Java 提供了一个名为finalize()的方法,可为我们的类定义它。
在理想情况下,它的工作原理应该是这样的:一旦垃圾收集器准备好释放对象占用的存储空间,它首先调用finalize(),而且只有在下一次垃圾收集过程中,才会真正回收对象的内存。
有时可能发现一个对象的存储空间永远都不会释放,因为自己的程序永远都接近于用光空间的临界点。
因为垃圾收集本身也要消耗一些开销。如永远都不用它,那么永远也不用支出这部分开销。
之所以需要finalize():看起来似乎是由于有时需要采取与Java的普通方法不同的一种方法,通过分配
内存来做一些具有C 风格的事情。
1. 将基本类型设为一个类的数据成员,会初始化;
2. 若定义成相对于一个方法的“局部”变量,编译器会强制程序员初始化该变量,否则报错。
// 不可妨碍自动初始化的进行,它在构建器进入之前就会发生。 class Counter { int i; Counter() { i = 7; } // 那么i 首先会初始化成零,然后变成7。
初始化顺序
// Demonstrates initialization order. // When the constructor is called, to create a Tag object, you'll see a message. class Tag{ Tag(int marker){ System.out.println("Tag(" + marker + ")"); } } class Card{ Tag t1 = new Tag(1); // Before constructor Card(){ // indicate we're in the constructor System.out.println("Card()"); t3 = new Tag(33); // re-initialize t3 } Tag t2 = new Tag(2); // after constructor void f(){ System.out.println("f()"); } Tag t3 = new Tag(3); //at end } public class OrderOfInitialization { public static void main(String[] args) { Card t = new Card(); t.f(); // shows that construction is done } } /* Tag(1) Tag(2) Tag(3) Card() Tag(33) f() */
// Specifying initial values in a class definition class Bowl { Bowl(int marker) { System.out.println("Bowl(" + marker + ")"); } void f(int marker) { System.out.println("f(" + marker + ")"); } } class Table { static Bowl b1 = new Bowl(1); Table() { System.out.println("Table()"); b2.f(1); } void f2(int marker) { System.out.println("f2(" + marker + ")"); } static Bowl b2 = new Bowl(2); } class Cupboard { Bowl b3 = new Bowl(3); static Bowl b4 = new Bowl(4); Cupboard() { System.out.println("Cupboard()"); b4.f(2); } void f3(int marker) { System.out.println("f3(" + marker + ")"); } static Bowl b5 = new Bowl(5); } public class StaticInitialization { public static void main(String[] args) { System.out.println("Creating new Cupboard() in main"); new Cupboard(); System.out.println("Creating new Cupboard() in main"); new Cupboard(); t2.f2(1); t3.f3(1); } static Table t2 = new Table(); static Cupboard t3 = new Cupboard(); } /* Bowl(1) Bowl(2) Table() f(1) Bowl(4) Bowl(5) Bowl(3) Cupboard() f(2) Creating new Cupboard() in main Bowl(3) Cupboard() f(2) Creating new Cupboard() in main Bowl(3) Cupboard() f(2) f2(1) f3(1) */
static初始化只有在必要的时候才会进行。如果不创建一个Table 对象,而且永远都不引用Table.b1 或
Table.b2,那么 static Bowl b1 和b2 永远都不会创建。然而,只有在创建了第一个Table 对象之后(或者
发生了第一次static 访问),它们才会创建。在那以后,static 对象不会重新初始化。
- 初始化的顺序是首先static(如果它们尚未由前一次对象创建过程初始化)
- 接着是非static 对象。
在这里有必要总结一下对象的创建过程。请考虑一个名为 Dog的类:
- 类型为 Dog的一个对象首次创建时,或者Dog 类的static方法/static 字段首次访问时,Java 解释器必须找到Dog.class(在事先设好的类路径里搜索)。
- 找到Dog.class 后(它会创建一个 Class对象,这将在后面学到),它的所有static初始化模块都会运行。因此,static初始化仅发生一次——在Class 对象首次载入的时候。
- 创建一个new Dog()时,Dog 对象的构建进程首先会在内存堆(Heap)里为一个 Dog对象分配足够多的存储空间。
- 这种存储空间会清为零,将Dog中的所有基本类型设为它们的默认值(零用于数字,以及 boolean和char 的等价设定)。
- 进行字段定义时发生的所有初始化都会执行。
- 执行构建器。
多维数组:
// Create multidimensional arrays public class MultiDimArray { static Random rand = new Random(); static int pRand(int mod){ return Math.abs(rand.nextInt()%mod + 1); } public static void main(String[] args) { int[][] a1 = { {1,2,3,}, {4,5,6,}, }; for(int i=0; i<a1.length; i++){ for(int j=0; j<a1[i].length; j++){ System.out.println("a1[" + i + "][" + j + "]= " + a1[i][j]); } } } } /* a1[0][0]= 1 a1[0][1]= 2 a1[0][2]= 3 a1[1][0]= 4 a1[1][1]= 5 a1[1][2]= 6 */
相关推荐
### 《Think-in-JAVA-4th-Edition》核心知识点概览 #### 一、书籍简介 《Thinking in Java》是一本由Bruce Eckel撰写的经典Java编程书籍,被誉为是学习Java的最佳参考资料之一。该书适合具有一定Java基础的学习者...
《Think in Java》是Java编程领域的一本经典著作,由Bruce Eckel撰写,中文版的出现使得更多中国程序员能够深入理解和掌握Java编程语言的核心概念。这本书以其深入浅出的讲解方式,深受程序员们的喜爱,是许多初学者...
装载的时候,所有static对象和static代码块都会按照本来的顺序初始化(亦即它们在类定义代码里写入的顺序)。保证这个顺序是非常关键的,因为衍生类的初始化可
Think-In-Java-Code Thinking In Java 书中源码以及课后练习代码(从第7章开始随着看书的进度一步步更新) 第七章 复用类 7.1 组合语法 7.2 继承语法 7.2.1 初始化基类 7.3 代理 7.4 结合使用组合和继承 7.4.1 确保...
《think java - java思维》是一本关于Java编程语言的入门书籍,它不仅仅教授读者Java的基础语法和结构,而且更重要的是培养编程思维。Java作为一种广泛使用的高级编程语言,其设计哲学是简单、面向对象和平台无关性...
作者:贯穿本书,我试图在您的大脑里建立一个模型——或者说一个“知识结构”。这样可加深对语言的理解。若遇到难解之处,应学会把它填入这个模型的对应地方,然后自行演绎出答案。事实上,学习任何语言时,脑海里有...
源码中涵盖了各种数据类型的使用,包括整型、浮点型、字符型、布尔型,以及如何声明、初始化和操作它们。 3. **控制流程**:源码涵盖了条件语句(if-else)、循环(for、while、do-while)和跳转语句(break、...
Think in Java(美)Bruce Eckel 著 陈昊鹏 译 引言 同人类任何语言一样,Java为我们提供了一种表达思想的方式。如操作得当,同其他方式相 比,随着问题变得愈大和愈复杂,这种表达方式的方便性和灵活性会显露无遗。 ...
《Think In Java 4》是Java编程领域里一本极具影响力的著作,由资深程序员 Bruce Eckel 编著。这本书以其深入浅出的讲解方式和全面的知识覆盖而闻名,被誉为Java学习者的经典读物。中文版的完美高清版本为国内读者...
5. **输入/输出(I/O)**:包括文件操作、流的概念、序列化和网络I/O,这些内容对于任何Java开发者来说都是必不可少的。 6. **多线程**:Java提供了内置的多线程支持,书中详细讨论了线程的创建、同步和通信,以及...
《Think in Java》是Bruce Eckel编写的Java学习...《Think in Java》是一本集系统性、全面性和实用性于一身的Java学习宝典,无论是作为教学书籍还是作为个人技术提升的资料,都值得每一位Java程序员收藏和反复阅读。
对于那些希望将Java作为职业生涯发展的工具的读者来说,《Think in Java 中文文档》不仅是一本自学材料,也非常适合高校和培训机构采用作为教材。本书内容全面,覆盖了Java编程的各个方面,能够帮助读者构建扎实的...
"Think in Java第三版代码"则提供了书中习题和示例的源代码,便于读者理解和实践。 在提供的压缩包文件中,我们可以看到以下文件: 1. `tij.jcsc`:这可能是《Think in Java》书中某个章节或习题的Java类文件,...
《Think in Java》是 Bruce Eckel 的经典著作,它深入浅出地讲解了Java编程语言的核心概念和技术。这本书强调理解编程思想,而不仅仅是学习语法。练习题是学习过程中的重要部分,它们帮助我们巩固理论知识,提升实际...
《深入思考Java》是一套备受推崇的学习Java编程的资源,其RAR压缩包“think-in-java.rar”包含了丰富的学习材料,旨在帮助程序员从基础到高级全面理解Java语言。这个压缩包的核心内容围绕“java 学习 面向对象”这三...
Think Data Structures Algorithms and Information Retrieval in Java-OReilly(2017)
java think in java (英文第四版)至今为止 被认为是java教程之中权威作品之一
Think in java 源码构建编译
think in java 第四版 源码以及作业 eclipse版本 包含jar包 可以直接导入eclipse
think in java 4高清免费版think in java 4高清免费版think in java 4高清免费版think in java 4高清免费版