memo


算法



运维


数据库


大数据


机器学习


量化交易


学术论文


C++


python


JAVA

Netty


Protocol buffers


技术Blog


前端


trading ststem


高性能服务器架构思路


Linux


书目

  • Promise Theory Principles and Applications

数学


其他


设计模式


数据结构


java

关于final的知识点

  • final 关键字可以用于成员变量, 本地变量, 方法以及类.
  • final 成员变量必须在声明的时候初始化或者在构造器中初始化, 否则就会报编译错误.
  • final 本地变量必须在声明时赋值.
  • final 变量不能够再次赋值.
  • 内部类只能访问外部类中的成员变量, 不能访问方法中定义的变量(内部类在外部类方法中定义). 内部类(定义在方法中的内部类)的参数必须是 final 变量. 本来内部类可以访问外部方法中所有的局部变量, 但是局部变量生命周期与内部类的生命周期并非一致, 为了避免内部类对象访问一个已不存在的局部变量, 解决方法是将变量设置为 final, 复制一份直接作为局部内部中的数据成员(final 保证复制品与原始值一致), 当内部类访问局部变量时, 其实真正访问的是这个局部变量的"复制品", 因此当运行栈中的真正的局部变量死亡时, 局部内部类对象仍可以访问局部变量.
  • final 关键字可以把方法锁定, 确保父类中的方法保持不变并不会被覆盖(重写).
  • final 类不能被继承.
  • final 关键字容易与 finalize() 方法搞混, 后者是在 Object 类中定义的方法, 是在垃圾回收之前被 JVM 调用的方法.
  • 接口中声明的所有变量必须是 final 的.
  • final 和 abstract 这两个关键字是互斥的, final 类就不可能是 abstract 的.
  • final 方法在编译阶段绑定, 称为静态绑定(static binding).
  • 没有在声明时初始化 final 变量的称为空白 final 变量(blank final variable), 它们必须在构造器中初始化, 或者调用 this()(调用本类中对应的构造函数, 通常为构造函数中的第一条语句) 初始化.不这么做的话,编译器会报错"final 变量(变量名)需要进行初始化".
  • 将类, 方法, 变量声明为 final 能够提高性能, 这样 JVM 就有机会进行优化.
  • 按照 Java 代码惯例, final 变量就是常量, 在系统中为宏变量, 编译的时候就已经分配好内存和值, 而且通常常量名要大写.
  • 对于集合对象声明为 final 指的是引用不能被更改, 但是你可以向其中增加, 删除或者改变内容. 譬如:
private final List Loans = new ArrayList();
list.add(“home loan”);  //valid
list.add("personal loan"); //valid
loans = new Vector();  //not valid

抽象类和接口的区别

  • 如果一个类没有包含足够多的信息来描述一个具体的对象, 这样的类就是抽象类.
  • 抽象类在实际应用中, 更多的是因为类中有抽象方法. 抽象方法: 只声明, 不实现. 具体的实现由继承它的子类来实现. 实际点就是:被 abstract 修饰的方法, 只有方法名没有方法实现, 具体的实现要由子类实现. 方法名后面直接跟一个分号, 而不是花括号.
  • 一个类中含有抽象方法(被 abstract 修饰), 那么这个类必须被声明为抽象类(被 abstract 修饰).
  • 接口在 java 中是是抽象方法的集合, 接口中没有构造方式(因为接口不是类)
  • 接口中的方法必须是抽象的(java8 中接口也通过 default 支持方法实现)
  • 接口中除了static, final变量, 不能有其他变量
  • 接口支持多继承(一个类可以实现多个接口, 一个子接口可以继承多个父接口)
  • 抽象类中可以有已经实现了的方法, 接口则不行
  • 抽象类的子类没有全部实现抽象方法, 则必须把自己也修饰成抽象类, 交给继承它的子类来完成实现.实现接口的类, 必须实现接口中的所有方法.
  • 抽象类可以有构造器, 而接口不能有构造器.
  • 抽象方法可以有 public, protected 和 default 这些修饰符, 接口方法默认修饰符是 public, 你不可以使用其它修饰符.
  • 抽象方法比接口速度要快.
  • 接口可以继承多个接口.
  • 接口中没有 this 指针, 没有构造函数, 不能拥有实例字段(实例变量)或实例方法, 无法保存状态(state), 抽象方法中可以.
  • 从设计理念上, 接口反映的是 "like-a" 关系, 抽象类反映的是 "is-a" 关系.
  • 除了默认方法, Java 8 还在允许在接口中定义静态方法.
  • 接口中的静态方法必须是 public 的, public 修饰符可以省略, static 修饰符不能省略.

泛型

  • 定义泛型的时候使用 SomeName, 对已经定义的泛型, 我们不想给她一个具体的类型做为类型参数, 我们可以给她一个不确定的类型作为参数 SomeName<?>
  • 在定义泛型类时, 任意一个大写字母都可以, 但为了提高可读性,大家还是用有意义的字母比较好,一般来讲,在不同的情境下使用的字母意义如下: E — Element, 常用在 java Collection 里, 如: List, Iterator, Set K, V — Ke, Value, 代表 Map 的键值对 N — Number, 数字 T — Type, 类型, 如 String, Integer 等等
  • Java 支持泛型类和泛型函数, 函数返回值如果是泛型, 函数定义时在返回值前加上标识泛型
  • static 方法无法访问泛型类的类型参数, 若要 static 方法支持泛型参数, 必须使其成为泛型方法
  • Class 和 Class<?> 代表 T 所对应的类
  • 受限通配, 表示 T 的一个未知子类
  • 受限通配, 表示 T 的一个未知父类
  • Class 的完整定义为: public final class Class extends Object implements Serializable, GenericDeclaration, Type, AnnotatedElement Class 类的实例表示正在运行的 Java 应用程序中的类和接口, 枚举是一种类, 注释是一种接口.
  • 类型擦除. 泛型是 Java 1.5 版本才引进的概念, 在这之前是没有泛型的概念的, 为了让泛型代码能够和之前版本的代码兼容. 泛型信息只存在于代码编译阶段,在 JVM 执行阶段, 与泛型相关的信息会被擦除掉, 专业术语叫做类型擦除. 泛型类被类型擦除的时候, 之前泛型类中的类型参数部分如果没有指定上限, 如 则会被转译成普通的 Object 类型, 如果指定了上限如 则类型参数就被替换成类型上限. 利用类型擦除的原理,用反射的手段就绕过了正常开发中编译器不允许的操作限制.

static

  • java 中静态属性和静态方法可以被继承, 但是没有被重写(overwrite)而是被隐藏.
    1. 静态方法和属性是属于类的, 调用的时候直接通过类名.方法名完成, 不需要继承机制就可以调用. 如果子类里面定义了静态方法和属性, 那么这时候父类的静态方法或属性称为 "隐藏". 如果你想要调用父类的静态方法和属性, 直接通过父类名.方法或变量名完成, 至于是否继承一说, 子类是有继承静态方法和属性, 但是跟实例方法和属性不太一样, 存在"隐藏"的这种情况.
    2. 多态之所以能够实现, 依赖于继承, 接口和重写, 重载(继承和重写最为关键). 有了继承和重写就可以实现父类的引用指向不同子类的对象. 重写的功能是: "重写" 后子类的优先级要高于父类的优先级, 但是"隐藏"是没有这个优先级之分的.
    3. 静态属性, 静态方法和非静态的属性都可以被继承和隐藏而不能被重写, 因此不能实现多态, 不能实现父类的引用指向子类的对象. 非静态方法可以被继承和重写, 因此可以实现多态.
  • static 代码块也叫静态代码块, 是在类中独立于类成员的 static 语句块, 可以有多个, 位置可以随便放, 它不在任何类方法体内, JVM 加载类时会执行这些静态的代码块, 如果 static 代码块有多个, JVM 将按照它们在类中出现的先后顺序依次执行它们, 每个代码块只会被执行一次.
  • 在静态方法里只能直接调用同类中其他的静态成员(包括变量和方法), 而不能直接访问类中的非静态成员, 也不能以任何方式引用 this 或 super. 这是因为, 对于非静态的方法和变量, 需要先创建类的实例对象后才可使用, 而静态方法在使用前不用创建任何对象.

Java 编码注意事项

  • Java 在构造子类的时候, 会先构造父类.

  • 在 Java 中, 构造方法无法被继承, 但是可以被重载, 同时类无法设置默认构造方法(如果不实现类的构造方法, 会添加默认构造方法, 如果实现了则不添加).

  • Jboss 同时是 Web 容器和 EJB 容器. Tomcat 只是Web容器.

  • HashMap 几乎可以等价于 Hashtable, 除了 HashMap 是非 synchronized 的, 并可以接受null(HashMap 可以接受为null的键值(key)和值(value), 而 Hashtable 则不行).

  • HashMap 是非 synchronized, 而 Hashtable 是 synchronized, 这意味着 Hashtable 是线程安全的, 多个线程可以共享一个 Hashtable; 而如果没有正确的同步机制的话, 多个线程是不能共享 HashMap 的.

  • 对于 volatile 变量, 写此类变量的时候会强制把将线程本地内存的数据刷新到主内存上, 读取的时候会将主内存的数据加载到本地内存里, 在线程间保证状态的一致性.

  • AtomicIntegerFieldUpdater使用

  • 容器中 entry 的删除要使用迭代器.

  • 一个类不想要外界创建其对象时, 可以将父类的构造函数私有化, 本类中提供返回对象的方法, 并且多数情况下提供的对象是唯一的,单例设计模式就是一个很好的例子,而当我们开发中需要保证对象唯一性的时候, 往往就采取这种做法.

  • 未初始化的 int 类型类变量默认值为 0.

  • 构造代码块的作用是给对象进行初始化, 有对象建立, 才会运行构造代码块, 且优先于构造函数执行, 构造代码块中定义的是不同对象共性的初始化内容.

  • 静态代码块随着类的加载而执行, 只执行一次, 并优先于主函数, 静态代码块其实就是给类初始化的, 而构造代码块是给对象初始化的, 静态代码块中的变量是局部变量, 与普通函数中的局部变量性质没有区别, 一个类中可以有多个静态代码块.

  • Java 类初始化顺序: Java类初始化顺序

    1. 访问SubClass.main(),(这是一个 static 方法), 于是装载器就会为你寻找已经编译的 SubClass 类的代码(也就是 SubClass.class 文件). 在装载的过程中, 装载器注意到它有一个基类(也就是 extends 所要表示的意思), 于是它再装载基类. 不管你创不创建基类对象, 这个过程总会发生. 如果基类还有基类, 那么第二个基类也会被装载, 依此类推.
    2. 执行根基类的 static 初始化, 然后是下一个派生类的 static 初始化, 依此类推. 这个顺序非常重要, 因为派生类的 "static 初始化" 有可能要依赖基类成员的正确初始化.
    3. 当所有必要的类都已经装载结束, 开始执行 main() 方法体, 并用 new SubClass() 创建对象.
    4. 类 SubClass 存在父类, 则调用父类的构造函数, 你可以使用 super 来指定调用哪个构造函数. 基类的构造过程以及构造顺序, 同派生类的相同. 首先基类中各个变量按照字面顺序进行初始化, 然后执行基类的构造函数的其余部分.
    5. 对子类成员数据按照它们声明的顺序初始化, 执行子类构造函数的其余部分.
  • 为了避免父类的构造函数调用子类的多态方法, 一般可以将父类的同名函数声明为 private, 这样在父类构造函数中调用的就是自己的方法.

    public class Test1 {
        public static void main(String[] args) {
            A b = new B();
            b.print();
        }
    }
    
    class A {
        public A(){
            print();
        }
    
        public void print(){
            System.out.println("A");
        }
    }
    class B extends A{
        int i = 1;
        public B(){
            print();
        }
    
        public void print(){
            System.out.println("B" + i);
        }
    }

docker

  • Docker-Cookbook
  • docker 要求必须部署在 64 位机器上
  • 容器内的数据是临时性的, 它会随着容器生命周期的结束而消失
  • 默认的 Docker volume (driver = ‘loclal’)不管是哪种形式, 本质上都是将容器所在的主机上的一个目录 mount 到容器内的一个目录, 因此, 它不具备可移植性.

英文缩写

  • TOE(TCP Offload Engine) TOE 技术, 即利用网卡上的专用处理器完成数据包的处理任务. 将用户数据直接拷贝到数据链路层, 通过 TOE 网卡驱动处理, 减少了传输层与网络层的数据拷贝, 降低了 CPU 负载, 在加快网络传输速度和网络响应的同时提高设备性能.

A Fiber is a lightweight thread that uses cooperative multitasking instead of preemptive multitasking. A running fiber must explicitly "yield" to allow another fiber to run, which makes their implementation much easier than kernel or user threads.

A Coroutine is a component that generalizes a subroutine to allow multiple entry points for suspending and resuming execution at certain locations. Unlike subroutines, coroutines can exit by calling other coroutines, which may later return to the point where they were invoked in the original coroutine.

A Green Thread is a thread that is scheduled by a virtual machine (VM) instead of natively by the underlying operating system. Green threads emulate multithreaded environments without relying on any native OS capabilities, and they are managed in user space instead of kernel space, enabling them to work in environments that do not have native thread support.