Java核心技术卷1ch3-6

《Core Java Volume 1》(Java核心技术卷1)读书笔记、代码。

Ch03

不可变字符串有一个优点:编译器可以让字符串共享。 共享(如复制字符串,常用)带来的高效率远远胜过于提取、 拼接字符串(少用)所带来的低效率。

public class Const {
    //      类常量
    public static final double MY_R = 5.0;

    public void oneMethod() {
        final double PI = 3.14;  // 常量 局部
        final double X;
        X = 4;
        double aaa = MY_R * PI * 2;
        double sinX = sin(PI);
    }
    public void otherMethod() {
        System.out.print(MY_R);        // 不同方法都可使用
        System.out.print(Const.MY_R);  // 其他类可使用(当MY_R为public)
    }

    public static void stringTest() {
        List<String> strings = new LinkedList<>();
        strings.add("连字符");
        strings.add("拼接");
        strings.add("字符串");
        System.out.println(String.join("-", strings));

        String text = "SubstringOfString";
        String copyText = text;
        if (text == copyText) {
            System.out.println("不可变字符串字符共享(内存仅一份)");
        }
        String subS = text.substring(0, 9);  // len = end - start = 9 - 0
        if (subS.equals("Substring") && "Substring".equals(subS)) {  // 也可以是字符串字面量"Substring"
            System.out.println("内容相同");
        }
        if (!(subS == "Substring")) {
            System.out.println("但存放位置不同(只有字符串常量是共享的,而+ 或 substring 等操作产生的结果并不是共享的)");
        }

        if (text != null && text.length() != 0) { // 先检查null
            System.out.println("text为null:无对象与text变量关联;text为空串:长度=0内容=“”的对象");
        }
    }

    static void test(int[] a) {
        a[0] = 11;
    }
    public static void arrayTest() {
        int[] a = {1, 2, 3};
        a = new int[2];  // [0, 0]
        a = new int[] {4, 5, 6, 7};  // 匿名数组

        int[] refA = a;  // 引用同一个数组
        refA[0] = 3;     // a[0] == 3
        int[] copyA = Arrays.copyOf(a, a.length);  // 拷贝到新数组
        copyA[0] = 2;    // a[0] == 3

        test(a);
        Arrays.sort(a);
        System.out.println(Arrays.toString(a));

        int[][] b23 = new int[2][3];
        int[][] c2x = new int[2][];   // 可创建不规则数组
        c2x[0] = a;
        c2x[1] = new int[10];
        System.out.println(Arrays.deepToString(c2x));

    }

    public static void main(String[] args) {
        arrayTest();
    }
}

Ch04 对象和类

OOP过程:

  1. 设计类(识别类->名词)
  2. 每个类中添加方法(方法->动词)

在 Java 中, package 与 import(非必须,只为简便) 语句类似于 C++ 中的 namespace 和 using 指令,而不是 include(必须)。

声明为 protected:如果需要限制某个方法的使用。这表明子类(可能很熟悉祖先类)得到信任,可以正确地使用这个方法,而其他类则不行。

public class Example {
    private int id;
    public Example(int id) {
        this.id = id;
    }
    public int getId() {
        return id;
    }
    public void setId(int id){
        this.id = id;
    }
    @Override
    public String toString() {
        return "Example{" +
                "id=" + id +
                '}';
    }
}

import static java.lang.System.out;
public class Class {

   private final String name;   // final域
   public Class(String name) {
       this.name = name;        // 若设置后不再被修改(无setName),使用final
   }
   public String getName() {
       return this.name;
   }
   private static int nextId = 1;  // 所谓静态域即类域:属于类,不属于对象,0或多个对象共享一个nextId域。(当该域与对象无关时使用)
   public static final double PI = 3.14;  // public的静态常量(如Math.PI)
   public static void staticMethod() {
       nextId++;
//        System.out.println(name);  静态方法不能访问name实例域,因为它不能操作对象
   }
   public void nonStaticMethod() {
       nextId++;
       System.out.println(name);
   }

   /**
    * 参数传递,一般有按值value传递、按引用reference传递,Java只有按值传递
    * Java有基本数据类型(数值、布尔)和引用类型(数组、类、接口)
    * 方法的参数为基本类型时不能修改原数据,如swap(int a, int b)无效
    * 方法的参数为引用类型时可以修改原数据的状态,如setId(Example e)、sort(int[] a)
    * 但不能使原数据引用新数据,swap(Example a, Example b)无效
    */
   public static void swap(Example e1, Example e2) {
       Example temp = e1;
       e1 = e2;
       e2 = temp;
       System.out.println("In swap() e1 e2 has swapped: " + e1.getId() + " " + e2.getId());
   }

   public static void Obj() {
       System.out.println(LocalDate.now());

       List<Example> examples = new ArrayList<>();
       Example example = new Example(1);
       examples.add(example);
       Example example2 = example;    // 指向同一内存
       example2.setId(2);
       examples.add(example2);
//        Example example3 = example.clone();  // error
       Date date = new Date();
       Date date2 = (Date) date.clone();         // 对象拷贝
       for (Example e : examples) {
           System.out.println(e);
       }

       Example E1 = new Example(1);
       Example E2 = new Example(2);
       swap(E1, E2);
       System.out.println("but E1 E2 didn't: " + E1.getId() + " " + E2.getId());
   }

}

// 初始化数据域的多种途径
public class StaticBlock {
    private int id;
    private static int nextId;
    private String name = "显示声明";

    public StaticBlock(){  // 在构造器初始化
        id = -1;
        nextId = 1;
    }

    public StaticBlock(int id, String name) {
        this.id = id;
        this.name = name;
    }

    public StaticBlock(int id) {
        this(id, "this()调用另一个构造器");
    }

    {      // 先于构造器执行
        System.out.print("object init block: " + id);
        id = 2;
        id *= id;
        id += nextId;
        System.out.println(" - " + id);
    }
    static {  // 类第一次加载时就执行
        System.out.print("static init block: " + nextId);
        nextId = 10;
        nextId *= nextId;
        System.out.println(" - " + nextId);
    }

    public int getId() {
        return id;
    }
    public static void main(String[] args) {
        StaticBlock sb = new StaticBlock(1);
        System.out.println(sb.getId());
        String s;
        out.println("导入静态包,System.out简写");
//        static init block: 0 - 100
//        object init block: 0 - 104
//        1

    }
}

Ch05 继承

抽象类:顶层的类,包含抽象的、通用的域、方法不能被实例化

public abstract class AbsPeople {
    private String name;
    public AbsPeople(String name) {
        this.name = name;
    }
    // 可以有(甚至全为)非抽象方法
    public String getName() {
        return name;
    }

    // 占位作用,待子类各自具体表述
    public abstract String getDescription();
}

扩展抽象类两种选择:

  1. 不实现或实现部分抽象方法,自身也为抽象类
  2. 实现全部抽象方法
public class Student extends AbsPeople {
    private String major;
    public Student(String name, String major) {
        super(name);
        this.major = major;
    }

    @Override
    public String getDescription() {
        return "major in " + major;
    }
}

类实现接口需要对接口所有方法给出实现。

public class Teacher extends AbsPeople implements Comparable<Teacher>{
    private double age;

    public Teacher(String name,double age) {
        super(name);
        this.age = age;
    }

    @Override
    public String getDescription() {
        return  "age of " + age;
    }

    @Override
    public int compareTo(Teacher o) {
        // 对于浮点数,防四舍五入,必须使用Double.compare()
        return Double.compare(age, o.age);  // o.age可以访问
    }
}

使用继承原则:is-a关系,如经理是雇员

public class Inherit {

    // 多态:一个对象变量(超类)可以指示多种实际类型(超类、子类、孙类)
    public static void Poly() {
        Example[] examples = new Example[2];
        examples[0] = new Example(1);
        examples[1] = new PeopleExample(2);
        out.println("e[0]: " + examples[0].getId());
        out.println("e[1]: " + examples[1].getId());
//        out.println(examples[1].getName());  // Error,声明类型为超类,不能调用子类方法
        PeopleExample people = new PeopleExample(3);
        out.println(people.getName() + people.getId());

        if (examples[1] instanceof PeopleExample) {
            people = (PeopleExample) examples[1];  // 超类转型成子类
        }
        out.println(people.getName() + people.getId());  // 现在可以使用getName()

    }

    // 抽象类
    public static void AbsClass() {
        AbsPeople people[] = new AbsPeople[2];
        people[0] = new Student("eyedeng", "CS");
        people[1] = new Teacher("hoping", 35);
        for (AbsPeople p :
                people) {
            out.print(p.getName() + ": ");
            out.println(p.getDescription());  // 可由超类变量调用,声明了抽象方法的好处
        }
    }

}

class PeopleExample extends Example {
    private String name;
    public PeopleExample(int id) {
        super(id);
        name = "Me";
    }
    @Override
    public int getId() {
        return super.getId() + 10;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getName() {
        return name;
    }
}

final class LastExample extends PeopleExample {
    String description = "final:不能被继承";
    public LastExample(int id) {
        super(id);
    }
}
Ch06 接口 lambda 内部类

接口中的所有方法自动地属于public。因此,声明方法时不必提供关键字 public。接口绝不能含有实例域 。

接口中的域将被自动设为 public static final(常量)。

public interface IntePeople {
    String LOCATION = "China";  // 常量 不必要声明为public static final(自动声明了)
    String getDescription();    // 不必要声明为public

}

服务提供商:如果类遵从某个特定接口,那么就履行这项服务。

package com.company.coreJava.v1ch06;
import com.company.coreJava.v1ch05.Teacher;

public class Interface {

    // 服务提供商:如果类遵从某个特定接口,那么就履行这项服务
    // Arrays.sort()服务:对象所属的类必须实现了Comparable接口
    public static void Sort() {
        Teacher t[] = new Teacher[4];
        t[0] = new Teacher("t1", 35.10001);
        t[1] = new Teacher("t2", 35.1001);
        t[2] = new Teacher("t3", 35.000000401);
        t[3] = new Teacher("t4", 35.0000004);
        Arrays.sort(t);
        for (Teacher te :
                t) {
            System.out.println(te.getName() + te.getDescription());
        }
    }
}

default方法:为接口方法提供一个默认实现,这样实现此接口时只需实现部分我所关心的方法。

接口演化(接口新增方法)时,如果是非默认方法,则不能保证源代码兼容(实现者都要跟着加)。

解决default方法冲突:

  1. 超类优先(当 interface Child extends Father)。

  2. 覆盖此方法解决接口二义性(当class C implements I1, I2)。

  3. 类优先原则。

lambda表达式来由:需要将一个代码块传递到某个对象(一个定时器, 或者一个 sort 方法)。这个代码块会在将来某个时间调用。在 Java 中传递一个代码段并不容易,必须构造一个对象,这个对象的类需要有一个方法能包含所需的代码(接口常用来封装代码,如ActionListener)。对于只有一个抽象方法的接口(称为函数式接口), 需要这种接口的对象时, 就可以提供一个 lambda 表达 式。最好把 lambda 表达式看作是一个函数(类比JS的箭头表达式函数),而不是一个对象,另外要接受 lambda 表达式可以传递到函数式接口。lambda表达式所能做的也就是转换为函数式接口

多年来,Java 程序员习惯的做法是用匿名内部类实现事件监听器和其他回调。如今最好还是使用 lambda 表达式。

public class TimerTest
{
    public static void main(String[] args)
    {
        // 原理
        ActionListener listener1 = new TimePrinter();

        // 过往做法:匿名内部类
        ActionListener listener2 = new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                System.out.println("At the tone, the time is " + new Date());
                Toolkit.getDefaultToolkit().beep();
            }
        };

        ActionListener listener3 = e -> {
            System.out.println("At the tone, the time is " + new Date());
            Toolkit.getDefaultToolkit().beep();
        };

        // 最佳,直接传入一个lambda表达式
        Timer t = new Timer(2000, listener3);
        t.start();
        
        JOptionPane.showMessageDialog(null, "Quit program?");
        System.exit(0);
    }
}

class TimePrinter implements ActionListener
{
    @Override
    public void actionPerformed(ActionEvent event)
    {
        System.out.println("At the tone, the time is " + new Date());
        Toolkit.getDefaultToolkit().beep();
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值