Thinking In Java 读书笔记

==========================

create by wythe             2016/2/15 21:49

在看TIJ之前,已经有了C/C++的一点基础。最近因为参加学校的软件编程比赛,做移动端的app,马马虎虎算是弄完了。在做得过程发现自己的java不熟悉(菜的一笔),所以闲时就看看这本经典,做些笔记

一 、 Introduction to Object
  • 主数据类型(Primitive Type)
类型 大小 默认值
byte 8 bits (byte)0
char 16 bits '\u0000'(null)
boolean 1 bit false
short 16 bits (short)0
int 32 bits 0
long 64 bits 0L
float 64 bits 0.0f
double 64 bits 0.0d

若主数据类型属于一个类成员,则会以上述的默认值初始化。但是局部变量会得到随机值
99

二 、 Everything is Object
  • String str = new String("hello world") str为句柄

    Java通过句柄(str)来操作对象;
    句柄(str)在它的作用域(Scope)终点自动销毁,然而句柄指向的对象还占据内存空间;

  • 内存
类型 作用
寄存器(Registers) 我们没有直接控制权,只能由编译器分配
堆栈(The stack) 对象句柄的储存的地方
堆(The heap) 对象的储存地方
  • 注意点

如果您的main()用package语句封装到一个文件里,那么必须在程序名前面指定完整的包裹名称,否则不能运行程序。

三 、 Operator
  • ==和!=运算符

关系运算符==和!=也适用于所有对象。下面是一个例子:

//:
Equivalence.java public class Equivalence { 
     public static void main(String[] args) {     
              Integer n1 = new Integer(47);    
              Integer n2 = new Integer(47);     
              System.out.println(n1 == n2);     
              System.out.println(n1 != n2);  
     }
} ///:~ 

其中,表达式System.out.println(n1 == n2)
可打印出内部的布尔比较结果。一般人都会认为输出结果肯定先是true,再是false,因为两个Integer对象都是相同的。但尽管对象的内容相同,句柄却是不同的,而==和!=比较的正好就是对象句柄。所以输出结果实际上先是false,再是true。这自然会使第一次接触的人感到惊奇。 若想对比两个对象的实际内容是否相同,又该如何操作呢?此时,必须使用所有对象都适用的特殊方法equals()。但这个方法不适用于“主类型”,那些类型直接使用==和!=即可。由于equals()的默认行为是比较句柄。所以除非在自己的新类中改变了equals(),否则不可能表现出我们希望的行为

  • 移位运算符

1、左移位运算符(<<)能将运算符左边的运算对象向左移动运算符右侧指定的位数
(在低位补0);
2、“有符号”右移位运算符(>>)则将运算符左边的运算对象向右移动运算符右侧指定
的位数。“有符号”右移位运算符使用了“符号扩展”:若值为正,则在高位插入0;若值为负,则在高位插入1;
3、Java也添加了一种“无符号”右移位运算符(>>>),它使用了“零扩展”:无论正负,都在高位插入0;

  • 主数据类型(int、long etc.)的二进制为补码形式,用以下代码验证
//:Main.java
//Test for Learning Java
package com.company;
import java.util.*;
public class Main {
    public static void main(String[] args) {
    // write your code here
        int i = -1;
        printIntBinary(i);
        printIntBinary(i>>3);
        printIntBinary(i>>>3);
    }
    static void printIntBinary(int a){
        for(int j = 31; j >= 0; --j) {
            if((( 1 << j ) & a ) != 0)
                System.out.print("1");
            else
                System.out.print("0");
        }
        System.out.println();
    }
}
///:The end~

结果:


Thinking In Java 读书笔记_第1张图片
结果
  • javadoc sample.class

通过代码的注释,自动生成api文档 教程

四 、 Initialization & Clean up
  • 对象初始化

static变量在非static变量前初始化
示例:

class Man{
    static int cnt;
    String name;
    //static区块用于初始化static变量
    static{
        cnt=1;
    }
    //非静态变量的初始化区块,支持"匿名内部类"的初始化
    {
        name = "Mike";
    }
    Man(){
        cnt++;
    }
}
  • 数组初始化

1、主数据类型(int、char etc.):表达式int[] a = new int[size]产生长度为sizeint数组,初始化值为默认值0.
2、对象:表达式Interger[] a = new Interger[size]产生一个句柄数组,具体的对象空间未分配。此时,数组元素的值为null。通过a[i] = new Interger(2)来关联对象.

  • 多维数组

多维数组可以任意指定各维的大小
示例:

int [][][] a = new int[randInt()][][];
for(int i = 0; i < a.length; ++i){
     a[i] = new int[randInt()][];
     for(int j = 0; j < a[i].length; ++j){
          a[i][j] = new int[randInt()];
          for(int k = 0; k < a[i][j].length; ++k)
                a[i][j][k] = i*j*k;
      }
}
  • finalize()方法

Java提供了一个名为finalize()的方法,我们可以在自己类中定义它。它的工作原理:当垃圾收集器准备好释放对象占用的储存空间,它会首先调用finalize(),而且只有在下一次垃圾收集过程中,才会真正回收对象内存。因此,可以用finalize()在垃圾收集期间进行一些重要的清除工作
示例:

//: initialization/TerminationCondition.java 
// Using finalize() to detect an object that 
// hasn’t been properly cleaned up.  
class Book {
    boolean checkedOut = false;
    Book(boolean checkOut) {
        checkedOut = checkOut;
    }
    void checkIn() {
        checkedOut = false;
    }
    protected void finalize() {
        if(checkedOut)
            System.out.println("Error: checked out");
// Normally, you’ll also do this:     
// super.finalize(); 
// Call the base-class version   
    }
}
public class TerminationCondition {
    public static void main(String[] args) {
        Book novel = new Book(true);
// Proper cleanup:  
        novel.checkIn();
// Drop the reference, forget to clean up:     
        new Book(true);
        // Force garbage collection & finalization:    
        System.gc();
    }
}
 /* Output: Error: checked out *///:~
五 、Access Control
  • 修饰符

1、friendly默认的访问修饰符,它不是显式的,不用特意来使用它。它指明可在包内访问,包外不可访问。
2、protected在包内访问上与friendly一致。但protected可访问性比friendly强。

可看以下图片,红色为语法错误


Thinking In Java 读书笔记_第2张图片
Package1

Thinking In Java 读书笔记_第3张图片
Package2
六 、Reusing Classes
  • final关键字

1、自变量final:例如,
void sampleMethod(final sampleClass s)中,无法改变自变量s句柄的指向(对象);
2、空白final:例如,

class blankFinal{
        final int i; 
        blankFinal(){
            i = 1;
        }
}

在对象初始化时,对final进行正确的赋值;

七、 Polymorphism
  • 多形性实例

//:Main.java
//Test for Learning Java
package com.company;
import com.company.tools.*;
class Instrument{
public void play(){
CustomPrint.print("Instrument~");
}
}
class Wind extends Instrument{
public void play(){
CustomPrint.print("Wind~");
}
}
class Brass extends Instrument{
public void play(){
CustomPrint.print("Brass~");
}
}
class Brass2 extends Brass{
public void play(){
CustomPrint.print("Brass2~");
}
}
public class Main {
public static void tune(Instrument isn){
isn.play();
}
public static void main(String[] args) {
Brass brass = new Brass();
Brass2 brass2 = new Brass2();
tune(brass);
tune(brass2);
}
}
///:The end~

![结果](http://upload-images.jianshu.io/upload_images/1623908-565bb364a569d2df.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
如果,
将上述的`play()`方法,加上static关键字`public static void play()`,则结果是:
![结果](http://upload-images.jianshu.io/upload_images/1623908-76d9edf55c437f8d.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

- 接口
>***1、接口介绍***
1)接口不规定方法主体;
2)接口可以声明**基本数据类型**的数据成员,它们都***默认***为static 和final;
3)与类相似,我们可在interface关键字的前面添加一个 public关键字(但只有接口定义于同名的一个文件内);或者将其省略,营造一种“friendly”状态;
4)接口中的方法声明默认为 public。所以在实现一个接口的时候,来自接口的方法***必须***定义成public。不然它们会默认为“friendly"
就像这样,

interface Instrument5 {
// Compile-time constant:
int i = 5; // static & final
// Cannot have method definitions:
void play(); // Automatically public
String what();
void adjust();
}

接口也具有多形性。下面这段代码的结果和`多形性实例`的结果一致:

//:Main.java
//Test for Learning Java
package com.company;
import com.company.tools.*;
interface Instrument{
void play();
}
class Wind implements Instrument {
public void play(){
CustomPrint.print("Wind~");
}
}
class Brass implements Instrument {
public void play(){
CustomPrint.print("Brass~");
}
}
class Brass2 extends Brass{
public void play(){
CustomPrint.print("Brass2~");
}
}
public class Main {
public static void tune(Instrument isn){
isn.play();
}
public static void main(String[] args) {
Brass brass = new Brass();
Brass2 brass2 = new Brass2();
tune(brass);
tune(brass2);
}
}
///:The end~

**2、接口实现“多重继承”**
>就像这样,`class samlpe implements interface1,interface2,interface3`。sample可以将类型上溯至interface1,interface2,interface3中的任意一种。下面是一个实例:

//: Adventure.java
// Multiple interfaces import java.util.*;
interface CanFight { void fight(); }
interface CanSwim { void swim(); }
interface CanFly { void fly(); }
class ActionCharacter { public void fight() {} }
class Hero extends ActionCharacter
implements CanFight, CanSwim, CanFly {
public void swim() {}
public void fly() {}
}
class Adventure {
static void t(CanFight x) {
x.fight();
}
static void u(CanSwim x) {
x.swim();
}
static void v(CanFly x) {
x.fly();
}
static void w(ActionCharacter x) {
x.fight();
}
public static void main(String[] args) {
Hero i = new Hero();
t(i); // Treat it as a CanFight
t(i); // Treat it as a CanSwim
v(i); // Treat it as a CanFly
w(i); // Treat it as an ActionCharacter
}
} ///:~

**3、接口能够继承接口**
>像这样`interface sample extends interface1,interface2,interface3`,形成更丰富的新接口
**4、接口产生枚举数组**
>就像这样,

public interface Months{
int
JANUARY = 1, FEBRUARY = 2, MARCH = 3,
APRIL = 4, MAY = 5, JUNE = 6, JULY = 7,
AUGUST = 8, SEPTEMBER = 9, OCTOBER = 10,
NOVEMBER = 11, DESEMBER = 12;
}

接口内的基本数据类型默认为***final*** **&** ***static***,可以***Months.JANUARY***的方式访问。

- 内部类
>**1、内部类,一个被定义在现有类内部的新类。**
像这样,

public class Parcel1 {
class Contents {
private int i = 11;
public int value() { return i; }
}
class Destination {
private String label;
Destination(String whereTo) {
label = whereTo;
}
String readLabel() { return label; }
}
public Contents cont(){
return new Contens();
}
public Destination to(){
return new Destination();
}
// Using inner classes looks just like
// using any other class, within Parcel1:
public void ship(String dest) {
Contents c = new Contents();
Destination d = new Destination(dest);
}
public void ship2(String dest){
Contents c = cont();
Destination d = to(dest);
}
public static void main(String[] args) {
Parcel1 p = new Parcel1();
p.ship("Tanzania");
Parcel.Contents c = p.cont();
}
}

**2、可在方法或者if语句等的作用域内内嵌一个内部类,但是这个内部类仅限在这个作用域内使用**
**3、匿名类,方法尾部return一个内部类**
像这样,

public Content cont(){
return new Content(){
private int i = 0;
public int value(){return i;};
}
}

new 表达式返回的句柄会自动上溯到Content,由此,可以重写Content的方法来隐藏实现细节1-·
**4、当一个新类继承一个外部类时,外部类内嵌的内部类不会被自动继承。因此,无法再新类中简单地覆盖内部类**
实例:

//: BigEgg.java
// An inner class cannot be overriden
// like a method
class Egg {
protected class Yolk {
public Yolk() {
System.out.println("Egg.Yolk()");
}
}
private Yolk y;
public Egg() {
System.out.println("New Egg()");
y = new Yolk();
}
}
public class BigEgg extends Egg {
public class Yolk {
public Yolk() {
System.out.println("BigEgg.Yolk()");
}
}
public static void main(String[] args) {
new BigEgg();
}
} ///:~

输出:New Egg( )
          Egg.Yolk( )
**5、可以用“外部类.内部类”的方式来继承内部类,并可用这种方法来覆盖父类内部类的方法**
下面是例子:

//: BigEgg2.java
// Proper inheritance of an inner class
class Egg2 {
protected class Yolk {
public Yolk() {
System.out.println("Egg2.Yolk()");
}
public void f() {
System.out.println("Egg2.Yolk.f()");
}
}
private Yolk y = new Yolk();
public Egg2() {
System.out.println("New Egg2()");
}
public void insertYolk(Yolk yy) { y = yy; }
public void g() { y.f(); }
}
public class BigEgg2 extends Egg2 {
public class Yolk extends Egg2.Yolk {
public Yolk() {
System.out.println("BigEgg2.Yolk()");
}
public void f() {
System.out.println("BigEgg2.Yolk.f()");
}
}
public BigEgg2() { insertYolk(new Yolk()); }
public static void main(String[] args) {
Egg2 e2 = new BigEgg2();
e2.g();
}
} ///:~

输出:   Egg2.Yolk()
          New Egg2()
          Egg2.Yolk()
          BigEgg2.Yolk()
          BigEgg2.Yolk.f()

#####八、Honding Your Objects
- continue配合标签使用,可以连跳多级循环
>```
retry:
    while(true){
        int t=
                (int)(Math.random()*flav.length);
        for(int j=0;j
  • 命令行下编译运行sample.java
    //cd 到com文件夹的上一级(如果是在IED(IJ)中生成的)

javac sample.java
//文件不含包名
java sample
//如果文件包含“package com.package”,则
java com.package.sample

还需要注意,“CLASSPATH=.;%JAVA_HOME%/lib/dt.jar;%JAVA_HOME%/lib/tools.jar”。其中,".;"表示当前路径

九、Strings
  • StringBuilder
  • 正则表达式

String mp = "\w+@(\w+\.)+[A-Za-z]{2,14}";
String mail = "[email protected]";
Pattern p = Pattern.compile(mp);
Matcher m = p.matcher(mail);

十、 Runtime Type Indente

你可能感兴趣的:(Thinking In Java 读书笔记)