- 对于访问修饰符,表示的是其所修饰的引用的可见性。例如一个类中有private的字符串引用,当拿到这个对象的引用的时候,不可以访问其内部的private的字符串引用,但是如果拿到了这个字符串引用,就可以直接调用这个字符串对象的公有的方法或者变量。
访问修饰符,表示的意思是拿到外层的对象的引用之后可不可以访问外出对象的内部的东西,但是这个和拿到内部的东西的引用之后能不能访问里面的东西没有关系。
- 创建一个空数组String[] strs = new String[0];的作用???有时候如果一个方法需要返回一个数组的引用,如果返回null,那么在调用的位置需要对返回值进行控制判断,也就是判断res == null,否则会报错,因为null没有length()等方法。如果返回一个空数组,则不需要判断引用是不是null,同时返回的这个引用包含length()等方法。
因为String是不可变的,所以new String(String old)在内部是直接把char数组的引用赋值过来,同时hashCode也赋值过来了。
Arrays.copyOf的用法。
java的Charset支持的编码方式中并没有unicode,unicode本身不是一个编码方法,得到的unicode的码点超过0xffff之后的不可以直接用两个字节数组进行表示。在string中使用的\u是码元,是utf16的码元,不是unicode的码点。如果在charsetName中填入了"unicode",则实际使用的是utf-16be的编码方式。
String的hashCode是根据String内部的字符的utf16码元值算出来的。所以包含相同字符的String的hashCode是相同的。
- 只是使用Class.class.getName(),使得虚拟机从文件系统中加载字节码文件,但是并不会执行类中的静态代码块。使用forName()的时候,会执行静态代码块的内容,该方法会触发类的初始化。
只有JVM创建Class类的对象。
- 定义一个类的时候,如果这个类实现了某个接口,而且这个接口是使用泛型定义的,那么在泛型的位置可以写上这个类的名字。在继承时同样可以。
public final class Integer extends Number implements Comparable<Integer> {}
- 补码0x80000000是-2^31,补码0x7fffffff是2^31-1,补码0xffffffff是-1。
- Integer的构造方法,如果传入字符串,只能传正确的整数字符串,科学计数法也不行。
在将字符串转换成整型的时候,要注意边界值的处理。
- parseInt(String, int)方法,基准值是0,然后把每个值从这个基准值开始往下减,是向下增长的。
- 自动装箱调用valueOf()方法。整形的自动装箱调用Integer.valueOf()的方法。
Integer的缓存机制和自动装箱机制。
- 在使用hashmap的时候,要确保key对象的不变性,也就是hash值不能改变。不同的对象可以有相同的hash值,但是hash值不同的对象一定不相同。
hashmap在使用的时候,需要用到hashCode方法和equals方法。
hashmap是数组,链表和rb-tree的数据结构的组合,使用数组进行hash寻址,使用链表存储冲突的entry,如果冲突的entry比较多,则使用rb-tree提高效率,链表长度大于8的时候转换成红黑树。
计算在table中的位置的表达式p = tab[i = (n - 1) & hash]) == null,其中n = table.length。hash是要放入的键的本身的哈希值和该哈希值无符号右移16位之后的异或的一个值。在hashmap中的node节点的hash值,不是简单的key的hashCode()的值,是异或后得到的一个值。
重写equals()方法之后要重写hashCode()方法的目的是为了,相同equals()的时候hashCode()需要相同。否则的话同样的对象放到hashmap中可能造成错误 。因为一开始从table中找位置的时候首先使用的是hash值,然后才使用equals()方法逐个进行比较。
- 写上import某个类,或者使用某个类声明一个引用变量的时候,并没有从文件系统中加载该类。但是在编译成为class文件的时候会找类是不是存在,完全限定名是不是唯一,某个类是否有对应的实例方法。
- 但是在执行的时候,只有需要用到该类进行初始化对象的时候才加载类并进行初始化。类加载的过程分为:加载,验证,准备,解析,初始化。
在源码的位置可以写import xx.xx.; 但是在编译之后,使用的是限定名,会具体到某个类,不会出现情况。也就是编译成为class文件的时候会搜索所有可能的类,但是在执行的时候会直接按照包名对应的路径加载类。
- null instanceof 都是返回的false。
instanceof 子类 * 父类 返回true ,但是父类 * 子类返回false。
instanceof 关键字是无法做到对称性的,可以使用getClass()方法。
.class属性得到的是编译时对象,getClass()方法得到的是运行时对象。在多态的场景下有区别。
在使用native方法的时候,首先需要加载库文件。可以使用System.loadLibrary()方法。在Object中的静态代码块中的registerNatives()方法应该是加载其他类库的方法。
- 在Class类中的实例方法getResource(String name)的时候,首先使用resolveName进行名字解析,主要的思路就是如果name不以/靠头就认为是个相对路径,把当前类的包名转换成目录添加到name的前面。
如果以“/”开头的,认为是一个绝对路径,在使用resolveName解析的时候就是把最前面的/去掉。
使用jdk中的getResource是从类路径中加载资源文件。因为ClassLoader把所有的路径都当作是类路径。查找指定文件名的过程和查找类文件的过程是类似的。
- url的语法中,://:@:/:?#
其中,在URL类中,user:password@host:port被当作authority部分。
如果一个接口使用的是泛型进行定义,接口中定义的方法有泛型参数。一个类实现这个接口的时候,如果指定具体的类,那么实现接口中的方法的时候需要使用指定的方法。如果在接口后面没有指定一个具体的类,那么实现的接口中的方法需要使用类Object。
在接口中一定不能出现实例域,虽然1.8之后可以出现一些default方法,但是这些方法不能引用实例域。
两个整数进行运算,可能造成溢出。两个整数相加或者两个负数相加。
两个浮点数通过减法比较大小,有时候会出现错误的结果。建议使用Double.compare()方法。
Arrays.sort()所有重载的方法中,没有要求数据的元素的类型实现了Comparable接口,但是在比较的时候使用了强制类型转换。
instanceof 运算符后面可以跟个接口。
- 接口中的可以定义常量,可以只写类型,接口中定义的变量是public, statid,final的。
接口中可以定义静态方法,但是习惯性的做法是把静态方法放到伴随类中,例如Array接口和Arrays伴随类。
接口中可以写静态方法和默认方法。
- 一些特殊的值。所以在进行浮点数比较的时候,大于或者小于的情况可以直接使用>或者<进行比较,其他的情况不能简单的认为是相等的。使用Double.compare()方法的唯一情况是一个NaN和一个数字进行比较的时候。定义NaN大于任何一个数,也就是比较的时候如果NaN在前面则返回1。
System.out.println(Float.NaN > Float.NaN); //false
System.out.println(Float.NaN < Float.NaN); //false
System.out.println(Float.NaN == Float.NaN); //false
System.out.println(Float.POSITIVE_INFINITY > Float.POSITIVE_INFINITY); //false
System.out.println(Float.POSITIVE_INFINITY < Float.POSITIVE_INFINITY); //false
System.out.println(Float.POSITIVE_INFINITY == Float.POSITIVE_INFINITY); //true
- 启动系统shell时的环境变量/usr/bin:/bin
- 使用用户登陆之后的环境变量/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/liu/.local/bin:/home/liu/bin
- 使用/bin/bash -l 之后的环境变量/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/home/liu/.local/bin:/home/liu/bin