一本不错的Java入门书
这篇书评可能有关键情节透露
八种基本类型 byte char int short long float double boolean
final 关键字表明初始化之后不可变。使用 final 修饰的方法不能被子类覆盖或隐藏。
使用 static 声明的方法是类方法,关联在类自己身上,而不是类的实例。
如果因为 return、continue 或 break 语句而离开 try 块,会先执行 finally 块,然后再转向 新的目标代码。
try with resources 语句更适合自动处理关闭资源等清理操作。
区分已检异常和未检异常,记住两点:异常是 Throwable 对象,而且异常主要分为 两类,通过 Error 和 Exception 子类标识。只要异常对象是 Error 类,就是未检异常。 Exception 类还有一个子类 RuntimeException,RuntimeException 类的所有子类都属于未检 异常。除此之外,都是已检异常。
变长参数列表本质上是数组列表。
类字面量为:Class<?> typePoint = Point.class;
自动转换和类型推导是 Java 实现 lambda 表达式的基础。
数组协变:数组中的元素类型是引用类型 T,而且 T 能指定给类型 S,那么数组类型 T[] 就能指定给数组类型 S[]。
数组的 length 字段是 int 类型,所以数组中的元素数量不能超过 Integer.MAX_VALUE。如果使用 long 类 型的表达式索引数组,即便运行时表达式的返回值在 int 类型的取值范围内,也会导致编译出错。
clone() 方法执行的是浅复制。如果数组的元素是引用类型,那么只复制引用,而不复制 引用的对象。因为这种复制是浅复制,所以任何数组都能被复制,就算元素类型没有实现 Cloneable 接口也行。
引用类型来说,有两种相等:引用相等和对象相等。使用“相同”(identical)表示引用相等,使用“相等”(equal)表示对象的 内容一样。若想测试两个不同的对象是否相等,可以在一个对象上调用 equals() 方法,然 后把另一个对象传入这个方法。
所有对象都(从 Object 类)继承了 equals() 方法,但是默认的实现方式是使用 == 测试引 用是否相同,而不测试内容是否相等。想比较对象是否相等的类可以自定义 equals() 方法。 可以在数组上调用 equals() 方法,但作用和使用 == 运算符一样,因为数组始终继承默认的 equals() 方法,比较引用而 不是数组的内容。比较数组是否相等可以使用 java.util.Arrays.equals() 实用方法。
java支持基本类型的自动装包和拆包。包装类有 Boolean Byte Short Character Integer Long Float Double
包的重要功能之一是划分 Java 命名空间,避免类名有冲突。
静态成员导入 使用import static。
静态成员属于类本身,而非静态成员关联在类的 实例上。常见的成员有四种:类字段、类方法、实例字段和实例方法。
子类继承超类的成员,而且可以声明新成员,或者使用新的实现覆盖继承的方法。
从 Java 8 开始,接口可以使用关键字 default 指明其中的方法是可选的。如果方法是可选的,接口文件必须包含默认的实现。实现接口的类必须为接口的非默认方法提供主体。实现某个接口的类的实例,也是这个接 口类型的实例。
Java 五种基本引用类型:类 ,接口,数组,枚举和注解。
abstract 修饰的类未完全实现,不能实例化。只要类中有 abstract 修饰的方法,这个类就必须使用 abstract 声明。
final 修饰符指明这个类无法被扩展。类不能同时声明为 abstract 和 final。
transient 这个修饰符指明字段不是对象持久状态的一部分,无需跟对象的其他内容一起序列化。
volatile 这个修饰符指明字段可被两个或多个线程同时使用。字段的值必须始终从主存储器中读取和释放,不能被线程缓存(在寄存器或 CPU 缓存中)。
公开的静态字段其实就是全局变量。类字段的名称会被定义它的类名限定,因此, 如果不同的模块定义了同名的全局变量,Java 也不会出现其他语言遇到的名称冲突问题。
关于静态字段,字段的值只有一个副本。字段关联在类自身上,而 不是类的实例身上。
可以这样理解:在任何实例中,总有一个 this 引用指向当前对象,但类方法不关联在具体的实例身上,所以没有 this 引用,因此不能访问实例字段。
类方法只能使用类字段和类方法,而不能使用实例字段或实例方法。实例方法 没有这种限制,不管类中的成员有没有声明为 static,实例方法都可以使用。
一个类可以有任意多个静态初始化程序。各个初始化程序块的主体会和所有静态字段的初 始化表达式一起合并到类初始化方法中。static {}
如果声明类时使用了 final 修饰符,那么这个类无法被扩展或定义子类。
Object 是特殊的类,原因如下:
• 它是 Java 中唯一一个没有超类的类;
• 所有 Java 类都从 Object 类中继承方法。
super 是 Java 的保留字。它的用法之一是,在子类的构造方法中调用超类的构造方法。 这种用法和在一个构造方法中使用 this() 调用同一个类中的其他构造方法类似。
只要创建对象,就会调用一系列构造方法,从子 类到超类,一直向上,直到类层次结构的顶端 Object 类为止。因为超类的构造方法始终在 子类的构造方法的第一个语句中调用,所以 Object 类的构造方法的主体始终最先运行,然后运行 Object 的子类的构造方法,就这样沿着类层次结构一直向下,直到实例化的那个类 为止。
覆盖方法的返回值类型可以是原方法返回值的子类。这 叫作协变返回(covariant return)。
如果类的成员声明为 protected,那么包里的所有类都能访问这个成员(等同于默认的包访问规则),而且在这个类的任何子类的主体中也能访问这个成员,而不管子类在哪 个包中定义。
如果声明类的成员时没使用任何修饰符,那么使用默认的访问规则(有时叫包访问), 包中的所有类都能访问这个成员,但在包外部不能访问。
Java 规范规定:
• 子类继承超类中所有可以访问的实例字段和实例方法;
• 如果子类和超类在同一个包中定义,那么子类继承所有没使用 private 声明的实例字段和方法;
• 如果子类在其他包中定义,那么它继承所有使用 protected 和 public 声明的实例字段和方法;
• 使用 private 声明的字段和方法绝不会被继承;类字段和类方法也一样;
• 构造方法不会被继承(而是链在一起调用)。
如果不确定该使用 protected、包还是 private 可见性,那么先使用 private。如果太过严格,可以稍微放松访问限制。
使用 static、private 和 final 声明的方法不能是抽象方法,因为这三种方法在子类中不能覆盖。类似地,final 类中不能有任何 abstract 方法。
里氏替换原则:子类的实例可认为是超类的实例。
一个类只能扩展一个超类,但可以实现任意多个接口。
类型擦除:泛型的类型参数只在编译时可见——javac 会去掉类型参数,而且在字节码中不体现出来。
Producer Extends, Consumer Super
注解不能影响程序的执行,只能为编译器和其他预执行阶段提供信息。
java嵌套类型有 静态成员类型,非静态成员类,内部类(在某方法中定义一个类),匿名类。
例如LinkedStack$Linkable.class,其中,$ 由 javac 自动插入。这个类文件中包含的就是静态成员接口 Linkable 的实现。
MyObject::toString 为方法引用。
基本值和对象引用的主要区别是,基本值不能修改——2 永远都是 2,而对象引用的内容 一般都能修改——一般称这种修改为对象内容的变化(mutation)。
java是值传递语言。
Object 类中的 toString() 方法返回的字符串由对象所属的类名和对象的十六进制形式哈希码(由 hashCode()方法计算得到)组成。
== 运算符测试两个引用是否指向同一个对象。如果要测试两个不同的对象是否相等,必须 使用 equals() 方法。任何类都能覆盖 equals() 方法,定义专用的相等比较方式。Object. equals() 方法直接使用 == 运算符,只有两个对象是同一个对象时,才判定二者相等。
只要覆盖了 equals() 方法,就必须覆盖 hashCode() 方法。hashCode() 方法返回一个整数, 用于哈希表数据结构。如果两个对象经 equals() 方法测试是相等的,它们就要具有相同的 哈希码。不相等的对象要具有不相等的哈希码(为了哈希表的操作效率),这一点很重要, 但不是强制要求,最低要求是不相等的对象不能共用一个哈希码。
clone方法的使用:你的类必须实现 Cloneable 接口,并覆盖 clone() 方法,而且要把 clone() 方法声明为 public。
委托模式:某个特定类型的对象保存一个引用,指向一个兼容类型的附属对象,而且把所有操作都交给这个附属对象完成。这种技术一般使用接口类型实现。
单例模式:私有构造方法,提供同步的获取实例的唯一get方法。
// 不要捕获异常而不处理
try {
someMethodThatMightThrow(); } catch(Exception e){
}
// 不要捕获,记录日志后再重新抛出异常
try {
someMethodThatMightThrow(); }
catch(SpecificException e){
log(e);
throw e;
}
CMS 并发标记清除
G1 集中于处理垃圾多的区域
安全的面向对象程序定义为,通过调用对象的存取方法,把对象从一个 合法状态变成另一个合法状态。
synchronized 修饰的代码块或方法会发生一系列事件,详述如下:
(1) 线程需要修改对象时,会临时把对象变成不一致状态;
(2) 线程获取锁,指明它需要临时互斥存储这个对象;
(3) 线程修改对象,修改完毕后对象处于一致的合法状态;
(4) 线程释放锁。
volatile关键字指明,应用代码读取字段或变量前,必须重新从主内存读取值。同样,修改使用 volatile 修饰的值后, 在写入变量之后,必须存回主内存。
如果调用 sleep()、wait() 或 join() 方法时阻塞了某个线程,那么在表示这个线程的 Thread 对象上调用 interrupt() 方法,会让这个线程抛出 InterruptedException 异常。
public interface Iterator<E> { boolean hasNext();
E next();
void remove(); }
public interface Iterable<E> { java.util.Iterator<E> iterator();}
Map 对象不是 Collection 类型,但映射的 键可以看成 Set 对象,映射的值可以看成 Collection 对象。
使用队列时,最好选定一种处理失败的方式。例如,如果想在操作成功之前 一直阻塞,应该选择 put() 和 take() 方法;如果想检查方法的返回值,判 断操作是否成功,应该选择 offer() 和 poll() 方法。
lambda 的应用:过滤集合,映射集合到另一种类型,forEach遍历,reduce化简。
Java 使用 Pattern 类(在 java.util.regex 包中)表示正则表达式。p.matcher()
二进制补码,带符号的正数最常使用这种表示方式。为了有效使用,只需 记住两点:
• 所有位都为 1 的位组合表示 -1;
• 如果设定了高位,表示的是负数。
java.math.BigDecimal 类,这个类以小数形式实现任意精度的计算。但是依然表示不了1/3
java 8 新日期和时间 API,请用 LocalDate,弃用 Date
HTTP 是 Java 原生支持的最高层网络协议。这个协议非常简单,基于文本,在 TCP/IP 标准协议族的基础上实现。
网络:URL类和URLConnection类。一般不会直接用这些底层库直接写业务逻辑,而且使用成熟的网络封装库。
TCP 是互联网中可靠传输网络数据的基础,确保传输的网页和其他互联网流量完整且易于理解。
Java 使用 Socket 和 ServerSocket 类表示 TCP。这两个类分别表示连接中的客户端和服务器端。
IP 是传输数据的最低层标准,抽象了把字节从 A 设备移动到 B 设备的物理网络技术。
Class<?> myCl = getClass();获取类对象
类加载阶段:加载,验证,准备和解析,初始化。
JVM 不允许使用任何方式直接访问底层系统中的单个内存地址,因此 Java 代码无法干扰本地硬件和操作 系统。这些特意为 JVM 制定的限制在 Java 语言中也有体现,即 Java 不支持指针或指针运算。
反射是在运行时审查、操作和修改对象的能力,可以修改对象的结构和行为,甚至还能自我修改。
方法句柄 MethodType对象。
jrunscript以及jjs可以执行JavaScript代码。Nashorn将java class转化为javascript 对象,从而实现点调用。
javac,java,jar,javadoc,jdeps,jps,jstat,jstatd,jinfo,jstack,jmap,javap
java8紧凑配置。