0%

Docker cheat sheet

List

  • docker ps

    获取正在运行的image列表

    Run

  • docker exec -it container_id bash

    开启bash交互界面

Chapter 6 Interfaces and Inner Classes

6.1 Interfaces

  • Accessibility
    all methods are public
    all fields are public static final
    不要写访问符
  • 一个interface变量要指向一个具体的实例

6.2 Cloning

  • protected Object.clone( )
    • mutable 类型克隆的结果还是指向同一对象的引用,所以需要重写。
    • 因为是protected所以只能克隆自己的对象。如果属性包括其他对象则不能克隆。
  • 使用Cloneable接口进行deep clone
    • 实现clone方法,访问权限为public。
    • 方法内对调用自身属性的clone方法

6.3 Interfaces and Callbacks

  • 这种callback原理就是在功能类中参数是接口而不是具体实现。在实际使用时传入一个该接口的实现类。这样降低了类之间的耦合。

6.4 Inner Classes

  • 为什么要用内部类?

    • 可以直接使用外部类private域
      • 可访问外部类和自身域
      • 编译器自动在内部类构造方法中添加外部类引用来实现对外部类的访问
    • 其他类不可见

      • 只有内部类才能使用private访问符
      • 如果内部类为public,可这样新建内部类:

        1
        2
        OutterClass outerObject = new OutterClass();
        InnerClass innerObject = outerObject.new InnerClass();

        用此可见内部类的创建需要包含一个外部类的实例。

    • 匿名内部类方便定义callback
  • 编译器对内部类的实现
    • 就是简单的一个类,名为InnerClass$OuterClass
    • 内部类多出一个域用来引用外部类:final OuterClass this$0
    • 内部类访问外部类域:
      • 外部类多出一个静态方法:static Type access$0(OuterClass o);
      • 访问时执行access$0(this$0);
    • private InnerClass实现:default访问权限 + private构造方法
  • Local Inner Class
    • 在方法内定义Class
    • 不带访问符!!! 方法内有效
    • 优点是甚至对外部类隐藏。只有外部方法才能访问
    • 可访问方法的参数,但参数在方法中必须声明final。原因:
      该参数会被编译器加在内部类中作为一个属性。
      需要保证该属性和参数在引用同样的数据,所以要定义成final,即不能被更改。
    • 数组被定义为final仍可以更改其中的数据
  • Anonymous Inner Class
    新建一个匿名内部类实例

    1
    2
    3
    4
    5
    6
    7
    8
    9
    // 新建一个继承SuperClass类的匿名内部类。
    new SuperClass(construction parameters) {
    inner class methods and data
    }
    // 新建接口实现没有参数
    new Interface() {
    inner class methods and data
    }
    // 匿名内部类没有构造方法,如果是第一种继承父类的内部类,需使用父类的构造方法
    • double brace initialization
      1
      2
      // 外层中括号表示匿名内部类,内层中括号是对象初始化时执行的代码块
      ArrayList<String> a = new ArrayList<String> {{add("a");add("b");}} ;
  • static inner class

    • 用于不需要访问外界对象的内部类。
    • 只为外部类服务(比如一个类中一个返回最大值最小值的方法,新建一个静态内部类Pair,储存最大最小值,只用于这个类,没必要在包内新建一个类)
    • 接口内的内部类都是自动public static的

6.5 Dynamic Proxy

书里讲的完全看不懂。。。但是在网上找到了这篇文章,教你如何找刘德华唱歌跳舞。写得很好。

  • 总的来说分三个部分。一个是接口,比如“会表演”。一个实现类,比如“演员”。一个代理类,比如“经纪人”
  • 在经纪人方法内用Proxy.getNewInstance(ClassLoader classLoader,Interface[] interfaces,InvocationHandler handler)方法获取演员的代理,方法内的interface即为实现类实现的接口。
  • InvocationHandler实例即为具体的处理者接口。实现InvocationHandler时需要重写invoke(proxy, method, args)方法。其中method即为调用的接口的某一方法。可在method.invoke()前后增加操作(如果不加method.invoke()则实现类的方法不再执行)

学习笔记
12/07/2018 (P272 ~ P299)
花了很多时间在单位学习,已经到了300页了。之前估计在内部类那个部分即使是汉语版也看不太懂。现在已经可以明白作者在说什么了。之后如果有相关经验再回过头来看应该会更清晰了。
13/07/2018(P300 ~ P314 )
arrayList的初始化jeremie 之前在代码里用过,原来是这么回事啊!之前还以为是什么特殊的语法糖。

Chapter 5 Inheritance

5.1 Class, Superclass, Subclass

  • override
    • 子类重写方法的时候对于父类私有域需要用super.getter()获取
    • super不是引用,而是一个引导compiler调用父类方法的关键字
  • constructor
    • 因为子类没有访问父类属性的权限,所以必须通过父类的构造器,即super()或super(args)
    • super构造器必须是构造器的第一行(只有把父类的东西初始化了才能再初始化子类的多余部分)
    • 关于super 和 this 的比较
      Recall that the this keyword has two meanings: to denote a reference to the implicit parameter and to call another constructor of the same class. Likewise, the super keyword has two meanings: to invoke a superclass method and to invoke a superclass constructor. When used to invoke constructors, the this and super keywords are closely related. The constructor calls can only occur as the first statement in another constructor. The constructor parameters are either passed to another constructor of the same class (this) or a constructor of the superclass (super).
      两者的作用都是1. 调用方法 2. 调用构造器
  • polymorphism & dynamic binding
    敲黑板了。这个第一次法国实习前公司的面试里一道我没答上的愚蠢题目。我当时还问这个词英文是什么。转眼间不到一个月实习就要结束了。
    polymorphism: the fact that a variable can refer to multiple actual type
    dynamic binding: automatically selecting the appropriate method at run time
  • Inheritance hierarchies
  • Inheritance hierarchies: 多个类继承同一个类
  • inheritance chain:在hierarchies中从某个类到其祖先类的路径
  • liskov substitution principle 里氏替换原则

    • 当需要使用父类对象的时候都可以使用子类对象
      比如:可以将父类对象赋值为子类对象的实例
      即父类可以引用(refer to)任何其子类对象。
    • 注意下面这个例子

      1
      2
      3
      4
      5
      6
      super[] superArray;
      superArray[0] = subObject;
      //false
      superArray[0].subMethod();
      //true
      subObject.subMethod();

      从编译器的角度考虑。数组superArray中的元素是super类,不能使用子类方法。

  • Dynamic binding实现方式
    1. 假设调用c.f(param),编译器寻找所有c类和c的父类中符合条件的方法:
      • 可访问
      • 方法名为f
    2. overloading resolution
      匹配参数类型(检验签名)。如果只有一个,则调用该方法
    3. static binding
      private, static, final方法编译器直接绑定(因为这三种不存在同签名方法或是与类的继承无关),不需要区分,此为静态绑定。
      否则,调用方法由explicit parameter(即输入的参数param)的实际类型决定,在runtime时动态绑定。
    4. JVM根据c的类型决定。c的类中没有则找c的父类。
      JVM存在method table存放所有签名。每次调用类JVM去查看签名。
  • 多态好处
    extensible:superClass.method() 。当新加入一个superClass的子类并将superClass赋值为一个子类对象的时候,由于使用多态而不需要更改之前的代码
  • 避免继承
    • final 类:不能被继承
    • final方法:不能被override
  • casting
    子类转父类不需要casting
    父类转子类则需要(因为内容增加了)
    可能在运行时出现ClassCastException. 因此需要instanceof判断:

    1
    2
    3
    Superclass super;
    if(super instanceof Subclass)
    Subclass sub = (Subclass)super;

    null instanceof Class 总是返回false(因为null不引用任何类)

  • abstract class
    当一个类需要作为其他类的基础而不需要使用它的实例的时候,使用抽象类。抽象类可以定义具体方法或者抽象方法。当没确定具体实现时使用抽象方法。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    abstract class Person {
    private String name;
    public Person(String n) {
    name = n;
    }
    public abstract String getDescription();
    public String getName() {
    return name;
    }
    }

    子类实现全部抽象方法/子类没实现全部抽象方法(此时子类也必须为abstract

  • Protected access
    private, public, default(package visible), protected(default + subclasses)

5.2 object

  • every class extends object
    only primitive types are not objects
  • equals()
    • default: reference equals
    • implementation:
      1. If implement equals() for subclass, test super.equals(other) first
      2. this == otherObject ⇒ true
      3. otherObject == null ⇒ false
      4. getClass != otherObject.getClass() ⇒ false
      5. class cast: Class other = (Class) otherObject;
      6. return a.attribute1 == other.attribute1 && ……
    • Object.equals(attribute, other.attribute) for non-primitive classes (in case attribute == null)
  • Equality testing and Inheritance
    不要使用instanceof 来代替3的步骤。问题出在有subclass的时候。instanceof会通过子类(但getClass不会)。
    • Arrays.equals(a,b) 测试数组元素是否相同
    • 注意equals方法参数类型是Object!!!否则方法不是重写Object类的equals方法而是新建了另一个。
  • hashCode()
    • Object类hashCode()方法默认是根据对象在内存的地址
    • From java7: Objects,hashCode(object)
      explicit parameter 为null返回0,否则调用object的hashCode方法
    • 更简单的方法: Objects.hash(param1, param2, param3, …)生成hashCode
    • x,equals(y) ⇒ x.hashCode() == y.hashCode()
    • 重写hashCode方法的原因:在使用HashMap的时候,两个相同的key值应该返回相同的内容。如果不重写hashCode,Object类里的方法计算的是内存地址,一般不同。导致相同key值无法获得相同结果。
    • Arrays.hashCode()方法返回根据数组元素hashCode生成的hashCode
  • toString()
    1
    2
    3
    ClassA a = new ClassA();
    //a.toString() is called
    String str = "..." + a;

5.3 Generic Array Lists

  • ArrayList staff = new ArrayList<>();
    • <>: diamond syntax
    • ensureCapacity(100): 在达到100前不扩容(提高了效率)
  • Accessing elements
    • array.set(i, element); 等价于 array[i] = element;
      set只用来修改。添加用add
    • array,get(i);

5.4 Wrapper and Autoboxing

  • Wrapper
    Interger & int
  • Autoboxing (from java 5)
    by the compiler
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    	//autoBoxing
    list.add(3); ⇐ ⇒ list.add(Integer.valueOf(3));
    //unbox
    int n = list.get(i) ⇐ ⇒ int n = list.get(i).intVlaue();
    ```

    #### 5.5 Methods with a variable number of parameters
    * signature:
    public void method(ClassA... params)
    * params 类型为 ClassA[ ]

    #### 5.6 Enumeration Classes
    ```java
    public enum Size {
    //每个类型只有一个实例
    Size1(attr1), Size2(attr2)...;
    //实例的值,为私有属性
    private AttrClass attr;
    //实例化方法(私有方法,用于初始化)
    private Size(AttrClass attr) {this.attr = attr:}
    //公有getter
    public AttrClass getAttr(){
    return attr;
    }
    }
    // 获取属性值方法
    Size.Size1.getAttr();
    //返回Size.Size1, Size,Size2, ......
    Size[] values = Size.values();

5.7 Reflaction

  • Class

    • runtime type identification
      用来跟踪每个对象所属的类,JVM由此选出属于该对象的正确方法
      JVM针对每种类型只有一个Class对象,所以可以直接比较内存地址
      1
      2
      3
      4
      5
      6
      7
      8
      9
      String name = object.getClass().getName();
      Class cl = Class.forName("java.util.Date");
      //认证类的种类
      if(e.getClass() == AClass.class) {
      ......
      }
      //调用无参构造函数创建新实例,如无此函数则抛出异常
      e.getClass().newInstance();
      Class.forName("java.util.Date").newInstance();
  • 类加载顺序
    包含main方法的class先启动,加载它需要的所有类。这些类加载它们依赖的类。

    • Class c = object.class
  • 使用反射
    • java,lang.reflect包:Field, Method, Constructor
  • Generic Array
  • Invoke

Design hints for Inheritance

学习笔记
07/07/2018 ( P200 ~ P211)
周六一天只看了11页。。。至少早起了。而且在非工作日学习了。需要继续努力。好的开始。
08/07/2018 ( P211 ~ P221)
洲际赛LPL险胜,看得惊心动魄。继续努力才能安心看S8全球总决赛。你看看人家职业选手,doinb,mouse这种的,都是下放到各层联赛摸爬滚打好几个赛季才有所成,职业精神值得学习。
09/07/2018 (P222 - P249 )
11号记录。昨天晚上睡了会儿觉看了场世界杯。白天搞加密的学习也没看书。今天忽然理解坚持确实比数量要重要的多。每天10页三个月内就能搞定,20页更是一个月就完事儿了。但是如果不坚持下来很可能到最后连一本书都完成不了。不要贪快,学习乐在其中才是最重要的。每天10页书保底,一定要坚持下来。
12/07/2018 (P250 ~ P271)
用上班时间把这章最后一部分看完了。反射的部分后面有些东西就没记了。了解了一下能做什么,等到有需要的时候再回过头来学习吧。到目前为止记笔记的方式始终是边看边记。在考虑要不要做得更精致点。从下一章开始先浏览一定量的内容(比如一个小节),然后回过头来再整理。

Chapter 4 Objects and Classes

4.1 Intro

  • programming paradigm: oop vs structured procedural programming
    • structured: algo + data structures
    • oop: data structures + algo
  • Big problems:
    • 2000 procedures + global data
    • 100 classes * 20 methods + Object data
  • Encapsulation:
    • combine data + behavior in one package
    • hide implementation details from user of the object
    • access instance fields by methods
  • Relations between classes
    • Dependence (use - a): minimize the coupling
    • Aggregation (has - a)
    • Inheritance (is - a)

4.2 Using predefined classes

  • Object variable refers to an object (not contains)
  • Date: a point in time
    GregorianCalendar: dates in the gregorian calendar notation
  • mutator methods: change instance fields (setter, …)
    accessor methods: only accesss instance fields (getter)

4.3 Define a Class

  • implicit param: object before the method (this)
    explicit param: params in the signature of method
  • getter & setter vs. public attribut:

    • change the internal implementation whithoud affecting any code other than the methods

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      //Old version
      private String name;
      public String getName(){
      return name;
      }
      //New version
      private String firstName;
      private String lastName;
      //without getter: change everywhere that used aObject.name
      aObject.name ⇒ aObject.firstName + AObject.lastName;
      //with getter: only need to change the getter
      public String getName(){
      return firstName + lastName;
      }
    • do the error check or convert inside the getter/setter

  • Do not return a mutable object

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    private Date date;
    //return a Date
    public Date getDate(){
    return date;
    }
    //date attribut can be modified, so breaks encapsulation!!
    d = aObject.getDate();
    d.setTime(blabla);
    //do this way:
    public Date getDate(){
    return date.clone();
    }
  • a method of a class is permitted to access the private fields of any object of this class

  • final
    • must be initialized when the object is constructed (in constructure or declairation)
    • final + primitive type /immutable class
    • final method/attribut : can’t be overwrite/modified

4.4 static fields and methods

  • static
    • belongs to class not object
    • only one copy for 0 to any number of objects
  • static constants
    • static final
  • static method
    • no implicit param
    • has access to static field of the same class
  • Factory method
    • static method
    • creates various objects from a same class

4.5 method parameters

  • call by value: just get the value passed
    call by reference: method gets the location of the variable the caller provides
    • java always uses call by value
    • object references are passed by value(swap方法不起作用)
    • A method cannot modify a parameter of a primitive type (that is, numbers or boolean values).
    • A method can change the state of an object parameter.
    • A method cannot make an object parameter refer to a new object.
    • 最后说一句,就是Java是值传递,但是对于对象类型传递的值是一个引用。所以调用引用对象的方法是可以改变对象state的,但是没法改变引用的对象,因为传的是值,并不是引用。

4.6 Object construction

  • overloading: sevral methods have the same name but different parameters.
  • Constructor with no arguments:
    • a free no-argument constructor only when your class has no other constructors (otherwise create it if needed)
  • calling another constructure with this

    1
    2
    3
    4
    5
    6
    public Employee(double s)
    {
    // calls Employee(String, double)
    this("Employee #" + nextId, s);
    nextId++;
    }
  • Initialization Blocks

    • Class declarations can contain arbitrary blocks of code. These blocks are executed whenever an object of that class is constructed.
    • The initialization block runs first, and then the body of the constructor is executed.
      1. All data fields are initialized to their default values (0, false, or null).
        1. All field initializers(在属性声明时初始化) and initialization blocks are executed, in the order in which they occur in the class declaration.
        2. If the first line of the constructor calls a second constructor, then the body of the second constructor is executed.
        3. The body of the constructor is executed.
    • static block

      1
      2
      3
      4
      //executed when the class is first loaded
      static{
      //initialize static fields here
      }
    • All static field initializers and static initialization blocks are executed in the order in which they occur in the class declaration. (注意这个是类加载时执行,所以比类的对象生成的时间要早)

    • Destruction and finalize
    • finalize method
      • finalize() may be invoked on an object when it becomes garbage. Object’s implementation of finalize() does nothing—you can override finalize() to do cleanup, such as freeing resources.
      • The finalize() method may be called automatically by the system, but when it is called, or even if it is called, is uncertain. Therefore, you should not rely on this method to do your cleanup for you. For example, if you don’t close file descriptors in your code after performing I/O and you expect finalize() to close them for you, you may run out of file descriptors.

4.7 Packages

  • reason: garantee the uniqueness of class names
  • compiler locates classes in package: bytecodes in class file classes are referred in full package
  • import static

    1
    2
    3
    //importing not just classes but also static methods/fileds
    import static java.lang.System.*;
    out.println("Goodbye, World!"); // i.e., System.out
  • compile .java file of class in package a.b.c ⇒ .class file in subdirectory a/b/c

  • Package scope(范围)
    • private public
    • default: accessible in the same package

4.8 Class path

  • use .jar file

    • set class path

      1. class path is the collection of all locations that can contain class files
        格式:地址a:(windows中是;)地址b:地址c
        此处地址可以是文件路径(如:/home/user/classdir或.代表当前文件夹)
        也可以是jar包路径(如;/home/user/archives/archive.jar)
      2. Java 6开始支持通配符,如home/user/archives/‘\‘*代表archives下所有jar包(而不是class文件)
      3. runtime libraray files(jre/lib 和 jre/lib/ext)不需要导入
      4. compiler: 始终会在当前文件夹寻找
        JVM:只有.在classpath时才会在当前文件夹寻找类。class path默认含当前文件夹(即不设置的时候)。如果设置了而不含当前文件夹,则编译通过但运行不一定通过。
      5. JVM寻找类的过程:
        • 条件: class path = /home/user/classdir:.:/home/user/archives/archive.jar
          要找的类:com.horstmann.corejava.Employee
          
        • 在jre/lib 和 jre/lib/ext中找
        • 找/home/user/classdir/com/horstmann/corejava/Employee.class
        • 在当前文件夹找 com/horstmann/corejava/Employee.class
        • 在archiver.jar中找 com/horstmann/corejava/Employee.class
      6. compiler确定类全名的过程(注意JVM读取class文件。而class文件里类都是全名,所以不存在这一过程。只有compiler在将java文件转化成class文件时才需要定位引用文件的位置):

        • 如果类包含package全名: 结束
        • 否则按下列方式执行。条件:

          1
          2
          3
          import java.util.\*;
          import com.horstmann.corejava.\*;
          Employee e = new Employee();
        • 先找java.lang.Employee (因为java.lang包总是默认导入)

        • 再找java.util.Employee
        • com.horstmann.corejava.Employee
        • 在当前包中找Employee
        • 找到多个相同类报compile error
        • compiler比对源代码和class文件的版本。如class文件版本落后则更新

4.9 comments

(maybe) see later

4.10 Class design hints

学习记录

05/07/2018

P134 - P182
按这个进度大概九月份才能读完(还是在每天学习的情况下)。恩,现在不是讨论早晚的问题,而是先坚持下去。在上班没其他事情的情况下进度也不是很快,主要是有些地方还是挺需要动脑的。今天这一部分最主要的是类加载机制和Java的值传递。

06/07/2018

P183 - P199
干货比较多。比如package,classpath。注意compiler,JVM对于类加载的机制。
还有就是今天才发现外部类只有public和default两种。为什么没有private?因为private类无法被外部访问,没意义。为什么没有protected?因为protected只能被同包或子类访问。前者即是default,后者就意味着一个问题,如何控制该包能被什么类继承?如果所有类都能继承,即所有类都是子类,即所有类都能访问该类,那该类就是public。如果没有类可以继承,那该类就是default。如果只有部分类可以继承。那是哪一部分呢?无法指定。所以类的访问权限(而不是方法)最小就是同包。
还有就是一个Java文件只允许一个public类,同时文件名必须与类名相同。没在网上确认,我的理解是这在import的时候很有用,同时涉及JVM加载类机制。如果一个包使用另一个类,JVM就要去class path里通过文件系统找这个类。如果类名和文件名不同这个过程就会很复杂。
第四章终于在班上结束了。之后回家要开始第五章的学习了。

很惭愧地上网下了一个英文版pdf。想想两三年前就买了这本书的中文版,就又有些许的心安理得。重新看一遍吧。之前看了好几回都没能通过第四章的样子。如今两年过去做了些项目,应该会容易些。争取在年末前先过一遍。
前两章略过了,直接从基础概念看起。

Chapter 3

1. 基本类型

  • 整形(byte,short,int,long):存储空间,范围
  • 浮点(float,double):单双精度。使用BigDecimal类进行精确计算。
  • 字符(char):2bytes
    今天下午正好也在研究字符的东西。Java里的char是表示UTF-16 encoding下的code units。比如: System.out.println(“\uD835\uDD6B”)的结果是zz。注意一个code point是指在Unicode的code page中字符与代码的映射。在不同的caracter encoding下(UTF-8,UTF-16)一个code point对应不同数量的code unit。

2. 变量

  • final 不可变量
    使用static final在类中声明供所有内部方法使用。

3. 类型转换

原则是不丢失信息。比如byte => short => int =>long

4. enumerated type

1
2
enum Size { SMALL, MEDIUM, LARGE, EXTRA_LARGE }
Size s = Size.MEDIUM;

5. 字符串

  • substring

    1
    2
    String greeting = "Hello";
    String s = greeting.substring(0, 3);//'Hel'(0~2)

    这种方式优点是两个参数相减长度即为字符串长

  • immutable
    关于动机几乎类似月经贴了,总是记不住。
    首先字符串的改变本质是引用对象的改变。改变后之前字符串的是不可变的。
    为什么这样做?一方面这种方式不能直接修改字符,降低了效率。另一方面使字符串保存在常量池里,可以被共享,提高了效率。
  • Code point & Code unit

    1
    char ch = "𝕫".charAt(1);//返回的是这个Unicode code point在UTF-16下的第二个code unit值

    所以使用char是很危险的,因为supplementary characters是用一对儿code unit来表示而不是一个。而一个char表示一个code unit。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    //前序遍历字符串
    int cp = sentence.codePointAt(i);
    //Characters whose code points are greater than U+FFFF are called supplementary characters.
    if (Character.isSupplementaryCodePoint(cp)) i += 2;
    else i++;

    //后序遍历字符串
    i--;
    /**
    Determines if the given `char` value is a Unicode surrogate code unit.
    Such values do not represent characters by themselves, but are used in the representation of [supplementary characters](https://docs.oracle.com/javase/8/docs/api/java/lang/Character.html#supplementary) in the UTF-16 encoding.
    A char value is a surrogate code unit if and only if it is either a low-surrogate code unit or a high-surrogate code unit.
    **/
    if (Character.isSurrogate(sentence.charAt(i))) i--;
    int cp = sentence.codePointAt(i);

    注意两种遍历一种是以code point为单位,一种是以code unit为单位。

  • 字符串的连接
    (原来从开头就出现了面试基础知识。看来不是面试题难,而是书看的确实不够。真的都是最基础的点了。)

    1
    2
    3
    4
    5
    //好处是避免了多个String对象的创建
    StringBuilder builder = new StringBuilder();
    builder.append(ch); // appends a single character
    builder.append(str); // appends a string
    String completedString = builder.toString();

    这里还有一个月经问题就是StringBuffer和StringBuilder的区别。StringBuffer是线程安全的,实现原理是在某些方法上加了synchronize关键字。但是StringBuffer好像没什么人用了,因为线程安全对于字符串而言好像没什么意义。

6. 输入输出

  • 输入
    1
    2
    3
    4
    5
    6
    7
    8
    //console
    Scanner in = new Scanner(System.in);
    String aLine = in.nextLine();
    String aWord = in.next();
    int aInt = in.nextInt();
    //fileIO
    Scanner fileInput = nez Scanner(Path.get("x.txt"));
    PrintWriter out = new PrintWriter("output.txt");

7. control flow

  • do while
  • switch

    1
    2
    3
    4
    5
    6
    7
    8
    9
    switch(var) {
    case var1:
    ...
    break;
    case var2:
    ...
    break;
    ...
    }

    注意没有break则会继续进行判断。作者评价如下:

    This behavior is
    plainly dangerous and a common cause for errors. For that reason, we never use the switch
    statement in our programs.

  • break control flow

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    // break out of loop
    while(tset){
    ...
    break;
    ...
    }
    // break out of multiple nested loop
    // label + colon
    break_label:
    while{
    for(){
    if(){
    // out of all the loops
    break break_label;
    }
    }
    }
    //jumps here
  • array

    • copy array

      1
      2
      3
      int[] arrayA = arrayB;
      //modified also the arrayB
      arrayA[3] = 1;

      注意Java是传递引用。所以如果想新建数组使用Arrays.copyOf(arrayB, arrayB.length)方法。

    • 扩容
      Arrays.copyOf(arrayB, arrayB.length*2);
      
    • 彩票抽奖
      程序就不贴了。这里边的问题是如何从一个数组中取出几个不重复的随机数。要点是每次随机的数不是值而是index。这样当这个index里的值被保存后把最后一个值传到index里,同时把取值范围减一。这样最后一位就不会被计入下次抽取中,同时把上一个抽取到的值从数组中抹去。

学习记录

2018/06/28(P59~P90)

真的是常看常新。三年前快冬天的时候我还记得看这一章觉得很简单,其实里边内容很多。要见识的多了再回头看才能有更多收获。

2018/07/02 (P91-P112)

进度差了一些。

2018/07/03(P113-P134)

这个是4号记的笔记了。总体来说进度感觉有点慢。尝试要不要简略地过一遍然后把一个脉络记下来。但是总算完成了一章的学习。继续努力。

按照陈皓大神的观点,深入理解Java大概要掌握这些知识点。
从今天开个头。争取能在三年内先通读一遍并记录笔记。本来想的是两年内。想想又改成了三年。其实这么大岁数了,也没必要较真两年还是三年了。早就明白一个道理,只有坚持了下来和没有坚持下来的区别。所有的慢都不是失败,放弃才是

入门:

  • Core Java
  • Head First设计模式
  • Spring实战

进阶:

  • Effective Java
  • Java并发编程实战
  • Java性能权威指南
  • 深入理解Java虚拟机
  • 精通Spring4.x
  • 设计模式

终于把主题安装好了。整个建站过程耗时两晚,然而真正有价值的时间大概只有不到一个小时。本来的目的是开始记录自己学习编程的过程,结果创建博客就折腾了这么久,有点哭笑不得。

讲道理来说如今科技进步这么快理应出现各种傻瓜包,一个按键就解决所有问题。看来这种建站工具还是没能强大到这一点。从另一方面说明我对前端的构建工具一点也不熟悉。想想如果是导入个jar包或者import一个项目的话,即便没用过也不至于花这么久时间才完成目的。

一个比较有趣的事情是我没有选择github推荐的Jekyll(直到现在我也没弄明白这个词该怎么读)。由于官方不推荐在windows下安装,于是我在虚拟机上鼓捣了半天。先是用之前装的CentOS。结果花了好久的时间配置之后响应速度还是令人窒息。于是我又重新打开了Ubuntu。Ubuntu的桌面上还留着我16年写的C程序。而且因为是在挂起状态所以启动的瞬间让我也是有点恍惚,像是忽然回到了两年前的时光,时间一下在那个时刻定格了一样。所以计算机这个东西还是有点邪门的,这种印象可不是看看过去读过的书就能体会到的。总之唏嘘完之后我发现原因就是电脑的问题而不是虚拟机的问题。在浏览器和shell间切换的时候我感觉自己仿佛回到了1998年,那个时候什么都慢。网速低得能让你在图片加载的过程中身体由软变硬,再由硬变软。。。也不知道硬件升级都升级到哪了,资源全被傻逼windows给吃了。是时候把购买Mac提上日程了。我还是忘不了当年从南大退学回寝室的时候,看我之前的室友买了个Mac结果装了个windows系统。。。

好像有点跑题了。正经的事就是我运行shell的时候发现(其实是后来才发现)我的系统版本太低了,用apt-get install命令的时候系统提示有些文件无法验证,选择继续之后就是有些文件无法获取。这个时候我犯了一个过去就经常犯的错误,在发现解决方案看似有些复杂的时候轻易就想着逃避到另一种方案。网上给出的解决办法是手动吧apt的软件获取地址改成oldrelease开头的一个地址。最后证明得益于Linux命令行的强大,加起来一共不到六步操作。但是不懂linux的结果就是要手动改每一个地址。想想就头大。于是我想着能不能手动下载然后用makefile安装。结果Ruby安装过程还算顺利,虽然也是一堆warning,但总算给安装完了。Rubygem也是以次方式安装的。结果最后一步安装Jekyll的时候提示说少一个z**lib的压缩库?于是心态彻底爆炸,去吃了两包炸酱面。。。结果就是该走的坑终归要走。硬着头皮查了怎么解决旧版本url地址的问题,结果打了几行命令就搞定了。虽然最后还是没能解决安装Jekyll的问题,但是至少到那一步问题就不是之前那么简单了。github上有个人评论出这种问题是因为Ruby屎一样的依赖引用,所以即便只用一个版本也最好用Ruby的版本管理器来安装Ruby。我想想还是算了,第一次和Ruby的接触即便没什么大收获也算是窥见到这类脚本语言的尿性了,于是去查了下Hexo和Jekyll的对比。发现Hexo没有Jekyll那么多的依赖包,同时在windows下运行没有问题。这里要提一句就是我之前复制粘贴异常信息的时候如果搜中文经常能搜到分析了半天加上连篇的截屏结果最后结论是网络连接问题。。。卧槽。我当时的想法是想骂他一顿,当然是心里默骂。但是转念一想,自己也开始写博客了。究竟是该接着骂然后自己把博客写的更精致些呢还是屏蔽掉搜索引擎然后接着骂呢?还是说,从逻辑的角度,如果不能证明人家写这个东西就是为了让别人搜索到的,就没办法骂他,甚至也不该生气或者觉得这个人愚蠢。但是这么一本正经分析和记录解决方案到网上结果结论是网络连接故障。。。。。。我觉得还是no comment的态度好一点。其实大多数情况下我还是这些博客狂的受益者,虽然要花大量的时间筛选掉垃圾信息。国外的网站如果想来救急就相对没那么容易。除非问答网站正好问到自己心里去了。好像很少有人写垃圾博客的样子。这一点值得思考。我还是找时间看看怎么屏蔽搜索引擎好了。虽然这种脚本生成的网站不知道能不能像普通网站一样实现。

恩,总之一步步照着一个博客用Hexo实现了个人主页,在这两个晚上的最后一个小时之内。虽然中途碰到了久违的SSH认证的问题和因为漏掉一步操作污心烦躁于是删了项目重建耽误了一小点时间,总之事情是顺利解决了。其实仔细想想最重要的还真的是基础知识和知识面的问题,否则即便是从来没接触过的东西只要有相关经验还是很好想通的,比如linux,git,脚本语言这些东西,接触过之后大致也能明白安装的流程大概都是什么意思,这样碰到问题也知道该从哪下手。毕竟软件安装不像是家电安装,异常的情况还是挺容易出现的。所以从这个经历来看,到底是linux的用户体验好还是windows的用户体验好呢?我思考了十秒钟的结论是Java的用户体验还是很不错的。