《Think in Java》

断了今生、忘了曾经 提交于 2020-01-01 02:04:15

 

chapter 1 对象导论

面向对象程序设计(Object-oriented Programming ,OOP)

chapter 2 一切都是对象

字段和方法

若类的某个成员变量是基本数据类型,即是没有进行初始化,java也会确保它获得一个默认值。

  

局部变量没有默认值,必须初始化。

方法、参数和返回值

static 关键字

  

chapter 3 操作符

import static 是导入这个类中的静态方法,然后调用静态方法就可以直接用方法名,而不用"类名.",但要注意导入的方法名有相同的调用时会报错。

java操作符

  String 类支持“+”和“+=”。

优先级

关系操作符

  对于引用型数据,==和!=比较的是对象的引用,基本类型数据可以直接比较值。equals()可以比较引用型数据的值,equals方法内部是将引用型数据的值转换为基本类型并用== 比较。

字符串操作符

  如果表达式以一个字符串起头,那么后续所有操作数都必须是字符串型。

类型转换操作符

  

chapter 4 控制执行流程

逗号操作符

  for循环中用到逗号操作符。

for(int i=1,j=i+10;i<5;i++,j=i*2) {
            System.out.println("i="+i+",j="+j);
        }

Foreach 语法

  for(float x : f){} //f是一个数组或集合,x是其元素类型。

标签和goto

  Java需要使用标签的原因就在于有循环嵌套的存在。Java中没有goto语法,但它是java的一个保留字。

  

chapter 5 初始化与清理

默认构造器

  如果你写的类中没有构造器,则编译器会自动帮你创建一个默认构造器。如果已经定义了一个构造器(无论是否有参数),编译器就不会帮你自动创建默认构造器。

this关键字

  

  this关键字只能在方法内部使用,表示对“调用方法的那个对象”的引用。

在构造器中调用构造器

  

  构造器中只能调用一个构造器,语句必须置于构造器第一句。

  构造器只能被构造器调用,不能被其他任何方法调用。

清理:终结处理和垃圾回收

终结条件

class Book{
    boolean checkedOut=false;
    Book(boolean checkOut){
        checkedOut=checkOut;
    }
    void checkIn() {
        checkedOut=false;
    }
    protected void finalize() throws Throwable {
        if(checkedOut) {
            System.out.println("Error:checked out");
        }
    }
}
public class TerminationCondition {
    public static void main(String[] args) {
        Book novel = new Book(true);
        novel.checkIn();
        new Book(true);  //while(true){new Book(true);}
        System.gc();   //
    }
}

  

垃圾回收器如何工作

  引用计数:

  

class TestA{
  public TestB b;

}
class TestB{
  public TestA a;
}
public class Main{
    public static void main(String[] args){
        A a = new A();
        B b = new B();
        a.b=b;  //循环引用
        b.a=a;
        a = null;
        b = null;
    }
}

停止——复制

   

标记——清扫

  

成员初始化

  方法的局部变量必须初始化才能操作。类的数据成员是基本类型,都会默认赋予初始值。类中对象引用未被初始化,会被设置为null。

指定初始化

  1. 直接提供初值 int i=99;
  2. 创建对象并初始化 Depth d=new Depth();
  3. 通过调用方法提供初值 int i= fun(); int fun(){ return 11; };

  

构造器初始化

   构造器初始化发生在自动初始化(类成员的默认值)之后,构造器初始化实际上是覆盖了字段的默认值。

  类中,变量定义的先后顺序决定了初始化顺序,但都会在构造器执行之前初始化。

 静态数据初始化

  

显示的静态初始化

   

非静态实例初始化

  

  {}代码块在构造器之前执行。

 数组初始化

  定义数组:int[] a1;

  定义并初始化:int[] a1=new int[5]; 元素会被自动赋予默认值。

  定义数组并初始化:int[] a1={1,2,3,4,5}; 元素手动赋予初值。

  数组是一种特殊的对象:

        String y="df";
        int[] a1= {2,3,4};
        System.out.println(a1.getClass().getName());  //  [I
        System.out.println(y.getClass().getName());  //  java.lang.String

  打印出的对象名是‘[I’。[表示数组,后面紧跟的数组的类型。

  数组对象具有唯一固有成员length。

 可变参数列表

   

  printArray(对象1,对象2,对象3);

  指定了可变参数,编译器会自动传入的参数列表转换为一个数组,省去显示地编写数组语法。

 枚举类型

    

  

  enum可以在switch语句内使用。

chapter 6 访问权限控制

  public、protected、默认空、private

chapter 7 复用类

  调用main方法:

  

初始化基类

  继承体系中,构造器中第一行隐式调用父类无参构造器。

名称屏蔽

  @Override 注解 表示该方法是重写的方法,如果不存在重写编译器就会报错。

protected 关键字

向上转型

  

final关键字

final数据

  

空白final

  

  private final int j; 必须在域的定义处或每个构造器中用表达式对final字段赋值。

final 参数

  Java 允许在参数列表中以声明的方式将参数指明为final。这意味着你无法在方法中更改参数引用所指向的对象。

  

final 方法

  

final 和 private 关键字

  final 修饰方法无法被子类重写。

  private 修饰方法无法被子类重写(必须通过添加@Override来验证),但子类可以存在和父类同名的private修饰的方法,但该方法不是从父类继承来的。

public class A {
    final int i;
    public A() {
        i=4;
    }
    public final void fun1() {
        System.out.println(" A fun1");
    }
    private final void fun2() {
        System.out.println(" A fun2");
    }
    public void lfun3() {
        fun3();
    }
    private void fun3() {
        System.out.println(" A fun3");
    }
    
}
package cn.test;

public class B extends A{
    int i;
    private int b;
    
    public void fun2() {
        System.out.println(" B fun2");
    }

    public void fun3() { //如果给该方法添加@Override,将报编译错误。
        System.out.println(" B fun3");
    }
    
    
}
package cn.test;

public class TestExtends {
    public static void main(String[] args) {
        B b = new B();
        
        b.fun3();
        b.lfun3();
    }
}

final 类

  final 修饰类,无法被继承。final类中的方法隐式指定为final的。

初始化及类的加载

继承与初始化(P147)

 chapter 8 多态

package cn.test;
enum Note{
    MIDDLE_C,C_SHARP,B_FLAT;
}
class Instrument{
    public void play(Note n) {
        System.out.println("Instrument.play");
    }
}
class Wind extends Instrument{
    public void play(Note n) {
        System.out.println("Wind.play "+ n);
    }
}
public class Music {
    public static void tune(Instrument i) {
        i.play(Note.MIDDLE_C);
    }
    public static void main(String[] args) {
        Wind flute = new Wind();
        tune(flute);    //Upcasting
    }
}

  

方法调用绑定

  前期绑定

  后期绑定

产生正确的行为

  动态绑定

可扩展性

class Derived extends PrivateOverride{
    public void f() {
        System.out.println("public f()");
    }
}
public class PrivateOverride {
    private void f() {
        System.out.println("private f()");
    }
    public static void main(String[] args) {
        PrivateOverride po = new Derived();
        po.f(); //打印:private f()
    }
}

  

缺陷:域与静态方法

package cn.test;
class Super{
    public int field=0;
    public int getField() {return field;}
}
class Sub extends Super{
    public int field=1;
    public int getField() {return field;}
    public int getSuperField() {return super.field;}
}
public class FieldAccess {
    public static void main(String[] args) {
        Super sup=new Sub();
        System.out.println("sup.field="+sup.field+
                ",sup.getField()="+sup.getField());
        Sub sub=new Sub();
        System.out.println("sub.field="+sub.field+
                ",sup.getField()="+sub.getField()+
                ",sub.getSuperField()="+sub.getSuperField());
    }
}

// sup.field=0,sup.getField()=1
// sub.field=1,sup.getField()=1,sub.getSuperField()=0

  

  

  如果某个方法时静态的,它的行为就不具有多态性。

  静态方法是与类,而并非与单个的对象相关联。

继承与清理(P295)

构造器内部的多态方法的行为

协变返回类型(P164)

package cn.test;
class Grain{
    public String toString() {
        return "Grain";
    }
}
class Wheat extends Grain{
    public String toString() {
        return "Wheat";
    }
}
class Mill{
    Grain process() {
        return new Grain();
    }
}
class WheatMill extends Mill{
    Wheat process() {
        return new Wheat();
    }
}
public class CovariantReturn {
    public static void main(String[] args) {
        Mill m = new Mill();
        Grain g = m.process();
        System.out.println(g);
        m=new WheatMill();
        g=m.process();
        System.out.println(g);
    }
}

 用继承进行设计

package cn.test;
class Actor{
    public void act() {};
}
class HappyActor extends Actor{
    public void act() {
        System.out.println("HappyActor");
    }
}
class SadActor extends Actor{
    public void act() {
        System.out.println("SadActor");
    }
}
class Stage{
    private Actor actor = new HappyActor();
    public void change() {actor=new SadActor();}
    public void performPlay() {actor.act();}
}
public class Transmogrify {
    public static void main(String[] args) {
        Stage stage = new Stage();
        stage.performPlay();
        stage.change();
        stage.performPlay();
    }
}

纯继承与扩展

向下转型与运行时类型识别

chapter 9 接口

抽象类和抽象方法

关于编译时和运行时:

ConstantFolding.java文件:
public class ConstantFolding {
    static final int number1=7;
    static final int number2=4;
    static int number3=2;
    static int number4=8;
    public static void main(String[] args) {
        int product1=number1*number2;
        int product2=number3*number4;
    }
}
ConstantFolding.class反编译出的java文件:
// Decompiled by Jad v1.5.8e2. Copyright 2001 Pavel Kouznetsov.
// Jad home page: http://kpdus.tripod.com/jad.html
// Decompiler options: packimports(3) fieldsfirst ansi space 
// Source File Name:   ConstantFolding.java
public class ConstantFolding
{
    static final int number1 = 7;
    static final int number2 = 4;
    static int number3 = 2;
    static int number4 = 8;

    public ConstantFolding()
    {
    }

    public static void main(String args[])
    {
        int product1 = 28;//可见 number1*number2 在编译时处理的。
int product2 = number3 * number4; } }

接口(P172)

  接口中的成员变量隐式地加上了static和final。

  

完全解耦(P174)

通过继承类扩展接口

  接口可以继承接口

  interface C extends  A,B{ }  //B,C是接口

组合接口时的名字冲突

适配接口(P181)

接口中的域

  接口中的全局变量默认且必须是 static 和 final 的。修饰符自动是 public。

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

  可以反编译Months.class,所有字段都自动添加 public static final ~

 初始化接口中域

  接口中定义的域不可以是“空final”,但可以使用非常量表达式初始化。

  由于是static修饰,在类第一次加载时初始化。

嵌套接口

接口与工厂

 

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!