读一部分写一部分。
1、无限精度整数:BigInteger;无限精度小数:BigDecimal。
2、for-each循环:for(元素类型 元素名:容器名)。
3、输出二进制用包装类的(例:printBinaryInteger)方法。
4、参数类型相同,顺序不同也可触发重载,但不推荐使用。
5、标签标识符:标签名+:,仅用于跳出嵌套循环。continue 标签名 会到达标签位置并重新进入紧跟其后的循环;break 标签名 会到达标签位置,但不会进入紧跟其后的循环,实质上是跳出了所有循环(假设标签设置在最外层)。
6、涉及基本类型的重载:支持自动宽化(short-int),不支持自动窄化(int-short)(会报错)。
7、在构造器中可以用this(参数列表)调用另一个构造器,但必须将该语句放置在起始位置,且只能调用一个。
8、finalize()方法不等同于析构函数,它仅仅在调用了本地方法(C、C++等)的情况下才使用,用于人工恢复内存(同样要使用本地方法)。使用它的一个主要场合是用于验证对象终结条件。当对象可以被清理时,从逻辑上讲它必然会处于一种特定的状态(例如苹果被吃完),此时可在finalize()方法中进行判断,若非如此则可输出一行显示错误的代码(利用println、Log.i(android)等),这样就可以最终发现该种情况。
9、Java虚拟机只会在内存耗尽的情况下才会去执行垃圾回收以恢复内存。
10、局部变量未初始化编译器会报错;类成员未初始化会自动赋初值(false、0、null)。
11、Java中可以在定义类成员时赋初值,但是C++中不行。赋初值的方法有直接定值(基本类型)、使用new、调用方法等。
12、定义时赋初值发生在构造器之前,无论它们之间的相对位置如何。
13、成员初始化顺序:静态成员(首次使用时)——定义时赋初值——初始化块——构造器
14、可变参数列表使用:f(类名... 列表名),一般用for-each循环处理。可接受0个参数(多用于可变尾随参数,如果方法传入值需要用到可变参数,一般将其置于传入值列表最后)。可直接传入一个数组作为可变参数列表。
15、为避免歧义,一般只在重载方法的一个版本中使用可变参数列表。
16、protected同样提供包访问权限。
17、派生类初始化时会先调用基类的构造器,若基类没有默认构造器(无参构造器)则需要利用super关键词显式调用基类构造器,否则编译器会报错。
18、final修饰方法参数:只能读参数,不能改参数。
19、final修饰方法:禁止覆盖。
20、final修饰类:禁止继承。
21、final修饰基本数据类型:禁止修改值;修饰引用:禁止改变指向(指向的对象可以改变)。
22、若基类与导出类均有static成员变量,在第一次调用时是从基类的static成员变量开始初始化。
23、在导出类中,对于基类的private方法,最好采用不同的名字,因为这会对多态产生干扰(举例:基类A中private f()与导出类B中public f(),若调用语句A a = new B();a.f(),调用的是基类A中的f())。
24、静态方法不具有多态性。访问域同样无法多态(例如某个成员变量)。
25、若需设置清理方法,则应按照导出类——基类的顺序进行清理工作。
26、在构造器中应当尽可能地不要调用其他方法,特别是被覆盖的方法,这会导致难以预料的错误。
27、向下转型会产生ClassCastException。
28、接口中的方法只能是public的,实现接口时在接口内被定义的方法也只能是public的。
29、Adapter设计模式:接收传入接口,产生需要的接口
30、接口内的成员变量都是static final的,包括类。因此接口内的类只能是嵌套类。
31、若一个导出类同时继承了基类与接口,若基类与接口中含有相同(同名、同返回值,同参数)方法(注意基类不一定实现了该接口,且基类中该方法是public的),则可以视作导出类已经实现了该方法(不必显式说明)。
32、当生成一个内部类的对象时,此对象与制造它的外围对象就有了一种联系,因此它能够访问其外围对象的所有成员。内部类可通过 外部类名.this 获取外部类对象的引用。
33、利用内部类实现接口提供对操作外部类的方法给其他类使用,此时的内部类叫做闭包(closure)。这是实现回调的一种方法。
34、要想直接创建内部类的对象,必须使用(外部类的对象(非外部类名).new 内部类名()的方式。
35、内部类可以在方法以及作用域(if等)内定义。
36、若匿名内部类需要使用在其外部定义的对象,那么需要将这个对象设置成final的。
37、匿名类的初始化可以利用初始化块的方式实现。
38、接口内部不能直接放置代码,但可以放置内部类并实现一些方法,甚至实现接口本身。这可以用于创建一些公共代码。
39、若一个类继承自一个另一个类的内部类,那么这个类的构造函数必须传入那个外部类的一个对象引用,并在构造函数中调用其super()方法。
40、使用局部内部类而不是匿名内部类的一个理由:需要不只一个该内部类的对象。
41、利用泛型定义的容器中可放置对应类型的子类。
42、在容器内添加一组元素的方式:(1)利用Collection类的构造函数,接收用逗号分隔的一组元素或是一个List对象(2)利用Collection类的addall()方法(3)利用Collections类的addall(collection,element)静态方法。
43、Arrays.asList()方法返回的List对象底层为数组,在增删元素时可能产生问题,使用时应将其作为一个输入值传入一个collection中。
44、Iterator()通用方法:(1)next()获取下一个元素(第一次使用时返回的是首个元素)(2)hasNext()判断是否还有下一个元素(3)(可选)remove()删除最近由next()返回的一个元素,必须在使用过next()的情况下使用。
45、遍历Iterator通用方法:if(iterator.hasNext()) it.next();
46、实现Iterable<T> 接口允许类被用于foreach语句中(foreach语句接受任意实现了Iterable<T>的类的对象)。
47、若想实现自定义容器,可通过继承AbstractCollection类实现。
48、利用throw重新抛出异常,printStackTrace()方法的路径不变。要想更新这个信息,可以调用fillInStackTrace()方法,返回一个Throwable对象,并将其转型为Exception并抛出,或者是抛出一个新异常(利用new创建)。
49、异常链通过Throwable提供的initCause()方法实现。
50、只能在代码中忽略RuntimeException及其子类类型的异常,其他类型的异常处理由编译器强制实施。
51、无论异常是否抛出,finally语句总能得到执行。
52、即便是涉及到break、continue、甚至return语句,finally语句也会得到执行。因此可将清理工作至于其内。
53、当覆盖方法的时候,只能够抛出在基类方法的异常说明里面列出的那些异常。(void f() throws ...)。构造器不受这个限制,派生类构造器可以抛出任何异常,但必须包括基类构造器的所有异常。
54、创建需要清理的对象的通用方法:在创建需要清理的对象之后,立即进入一个try-finally语句块,并在finally中加入清理语句。典型应用:开闭输入输出流。
55、异常使用指南(在以下情况下使用异常):
(1)在恰当的级别处理问题。
(2)解决问题并且重新调用产生异常的方法。
(3)进行少许修补,然后绕过异常发生的地方继续执行。
(4)用别的数据进行计算,以代替方法预计会返回的值。
(5)把当前运行环境下能做的事情尽量做完,然后将相同或不同的异常抛出到更高层。
(6)终止程序。
(7)简化异常模式。
56、Exception的构造函数有无参与单个字符串参数两种。自定义时可利用super()。
57、拼接较大的字符串使用StringBuilder类。
58、%后加-代表左对齐(不足右边补空格),不加默认右对齐(不足左边补空格)。
59、构建格式化字符串利用String类的静态方法format,用法与C类似。
60、利用正则表达式分割字符串(split()方法)时,与正则表达式匹配的部分在结果中都不存在了。
61、构建正则表达式思路:构建正则表达式内容(本质)——思考如何在Java中输出该字符串(表象)。思考时要明确地将两步分离开。
62、正则表达式中匹配单个\要用\\\\(四个),原理同上(正则表达式中需要用\\表达匹配一个\,输出成字符串每个\需要用\\来表示)。
63、正则表达式量词:
X? 一个或零个X;
X* 零个或多个X;
X+ 一个或多个X;
X{n} 恰好n个X;
X{n,} 至少n个X;
X{n,m} 至少n个,不超过m个X。
这里的X可以是单个字符,也可以是用()包裹的多个字符。
量词默认为贪婪型(尽可能多的匹配),后加?为勉强型(尽可能少的匹配)。
注意:贪婪或勉强都要建立在有多种匹配方式的条件下,即不存在贪婪性能够匹配,而勉强性不能够匹配的情况。例:Never give up!用"Neve.*?!"可以匹配。
64、字符类:
[abc] a、b 或 c(简单类);
[^abc] 任何字符,除了 a、b 或 c(否定);
[a-zA-Z] a 到 z 或 A 到 Z,两头的字母包括在内(范围);
[a-d[m-p]] a 到 d 或 m 到 p:[a-dm-p](并集);
[a-z&&[def]] d、e 或 f(交集);
[a-z&&[^bc]] a 到 z,除了 b 和 c:[ad-z](减去);
[a-z&&[^m-p]] a 到 z,而非 m 到 p:[a-lq-z](减去);
. 任何字符(与行结束符可能匹配也可能不匹配);
\d 数字:[0-9] ;
\D 非数字: [^0-9];
\s 空白字符:[ \t\n\x0B\f\r];
\S 非空白字符:[^\s] ;
\w 单词字符:[a-zA-Z_0-9](注意包括_);
\W 非单词字符:[^\w] ;
\p{Lower} 小写字母字符:[a-z];
\p{Upper} 大写字母字符:[A-Z];
\p{ASCII} 所有 ASCII:[\x00-\x7F];
\p{Alpha} 字母字符:[\p{Lower}\p{Upper}];
\p{Digit} 十进制数字:[0-9];
\p{Alnum} 字母数字字符:[\p{Alpha}\p{Digit}];
\p{Punct} 标点符号:!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~ ;
\p{Graph} 可见字符:[\p{Alnum}\p{Punct}];
\p{Print} 可打印字符:[\p{Graph}\x20];
\p{Blank} 空格或制表符:[ \t];
\p{Cntrl} 控制字符:[\x00-\x1F\x7F];
\p{XDigit} 十六进制数字:[0-9a-fA-F];
\p{Space} 空白字符:[ \t\n\x0B\f\r];
65、反斜线字符 ('\') 用于引用转义构造,同时还用于引用其他将被解释为非转义构造的字符。因此,正则表达式 \\ 与单个反斜线匹配,而 \{ 与左括号匹配(正则表达式中有特殊含义)。在不表示转义构造的任何字母字符前使用反斜线都是错误的,它们是为将来扩展正则表达式语言保留的;可以在非字母字符前使用反斜线,不管该字符是否非转义构造的一部分。
66、正则表达式"\n"、"\\n"、"\\\n"都可与字符串"\n"匹配,原理如下:
一个\:传递一个\n字符用于匹配;
两个\:正则表达式中为"\n",表示换行符;
三个\:正则表达式中为"\\n",见65条。
关键点:正则表达式中的"\n"与字符串中的"\n"都表示换行符。
67、匹配单词要用\b单词\b,避免部分重叠,例如hi history high。
边界匹配器
^ 行的开头;
$ 行的结尾;
\b 单词边界;
\B 非单词边界;
\A 输入的开头;
\G 上一个匹配的结尾;
\Z 输入的结尾,仅用于最后的结束符(如果有的话);
\z 输入的结尾。
注意:边界匹配器匹配的都是“位置”而不是某个字符。
例:\bhi\b匹配的是单个hi单词,\shi\s匹配的是 hi 。
68、Pattern与Matcher构建方法:
(1)利用Pattern类的静态方法compile()传入正则表达式,构建Pattern对象;
(2)利用Pattern类的方法matcher()传入用于匹配字符串,构建Matcher对象;
(3)利用matcher类的方法reset()改变用于匹配的字符串。
使用方法:
(1)利用Matcher类的方法find()寻找下一个匹配的子序列,并用start()与end()方法获取子序列索引。
(2)利用Matcher类的方法group()获取在上一次匹配操作中(例:find())由指定组捕获的子序列。注意:因为整个子序列默认为第0组,因此实际组数=括号对数+1,因此在循环时条件应为i<=matcher.groupCount()(小于等于)。
(3)利用appendReplacement(StringBuffer sb,String replacement)一步步进行替换并保存。需要配合find()进行,每次将从开始位置到匹配替换结束位置的子序列添加入sb中。例:"a b c d e"利用appendReplacement(sb,"x")替换" "过程:ax-axbx-axbxcx-axbxcxdx,最后使用appendTail(sb)后结果为axbxcxdxe。
(4)利用appendTail(StringBuffer sb)将未匹配的剩余部分添加进sb中。
69、正则表达式中的组(group):用括号划分的正则表达式。例:A(B(C))D ABCD为组0,BC为组1,C为组2。
70、Pattern标记:
Pattern.CANON_EQ:
当且仅当两个字符的"正规分解(canonical decomposition)"都完全相同的情况下,才认定匹配。比如用了这个标志之后,表达式"a/u030A"会匹配"?"。默认情况下,不考虑"规范相等性(canonical equivalence)"。
Pattern.CASE_INSENSITIVE (?i)(?-i):
默认情况下,大小写不明感的匹配只适用于US-ASCII字符集。这个标志能让表达式忽略大小写进行匹配。要想对Unicode字符进行大小不明感的匹配,只要将UNICODE_CASE与这个标志合起来就行了。
Pattern.COMMENTS (?x)(?-x):
在这种模式下,匹配时会忽略(正则表达式里的)空格字符(注:不是指表达式里的"//s",而是指表达式里的空格,tab,回车之类)。注释从#开始,一直到这行结束。可以 通过嵌入式的标志来启用Unix行模式。
Pattern.DOTALL (?s)(?-s):
在这种模式下,表达式'.'可以匹配任意字符,包括表示一行的结束符。默认情况下,表达式'.'不匹配行的结束符。
Pattern.MULTILINE (?m)(?-m):
在这种模式下,'^'和'$'分别匹配一行的开始和结束。此外,'^'仍然匹配字符串的开始,'$'也匹配字符串的结束。默认情况下,这两个表达式仅仅匹配字符串的开始和结束。
Pattern.UNICODE_CASE (?u)(?-u):
在这个模式下,如果你还启用了CASE_INSENSITIVE标志,那么它会对Unicode字符进行大小写不明感的匹配。默认情况下,大小写不明感的匹配只适用于US-ASCII字符集。
Pattern.UNIX_LINES (?d)(?-d):
在这个模式下,只有'/n'才被认作一行的中止,并且与'.','^',以及'$'进行匹配。
71、 (?:pattern)
匹配 pattern 但不获取匹配结果,也就是说这是一个非获取匹配,不进行存储供以后使用。这在使用 "或" 字符 (|) 来组合一个模式的各个部分是很有用。例如, 'industr(?:y|ies) 就是一个比 'industry|industries' 更简略的表达式。
(?=pattern)
正向预查,在任何匹配 pattern 的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如,'Windows (?=95|98|NT|2000)' 能匹配 "Windows 2000" 中的 "Windows" ,但不能匹配 "Windows 3.1" 中的 "Windows"。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始。
(?!pattern)
负向预查,在任何不匹配 pattern 的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如'Windows (?!95|98|NT|2000)' 能匹配 "Windows 3.1" 中的 "Windows",但不能匹配 "Windows 2000" 中的 "Windows"。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始
72、可用String类的方法format()模拟C中sprintf()函数。
73、扫描复杂字符串(例如.txt)可利用Scanner类。支持正则表达式扫描。步骤:scanner.next(regex);-MatchResult match = scanner.match();
74、可以使用类名.class获取特定类的Class对象引用。如果已经有了一个特定类的实例,则可利用对象的getClass()方法。
75、使用Class类的方法newInstance()的前提条件是类拥有默认构造器。调用该方法会得到InstantiationException与IllegalAccessException两种异常。
76、a instanceof B 返回一个布尔值,代表a是否是B的实例(A是B的派生类也成立)。B只能是命名类型而不能是Class对象。实际使用时多用Class类的方法isInstance()。
77、若将泛型语法<?>用于Class对象,那么newInstance()将返回确切类型,而不是Object。
78、Class类方法a.isAssignableFrom(Class b):若a是b的父类或a与b属于同一个类则返回true。
79、利用File类方法list()或者listFiles()获取目录下所有文件的信息。注意:File对象需指向一个目录,若指向的是某个文件则需要调用getParentFile()方法。若需要提取具有特定扩展名的文件,可利用list(FilenameFilter)方法,提供FilenameFilter接口进行过滤。
80、在switch()语句中使用枚举类型时,case后不必使用enum.XXX,直接使用XXX即可。
81、编译器自动会为每个enum类添加一个静态方法values(),可用循环遍历enum类所有内容。
82、可利用Class类的方法getEnumConstants()方法获取enum类内容。
83、所有enum类都继承自Enum类,因此不能再继承其他类,但可以实现接口。
84、利用泛型实现方法返回多个对象:
public class TwoTuple<A,B>{
public final A first;
public final B Second;
public TwoTuple(A a,B b) {first = a;second = b;}
}
85、定义泛型方法需要将泛型参数列表置于返回值之前。
86、使用泛型类时,必须在创建对象的时候指定类型参数的值,而使用泛型方法的时候,通常不必指明参数类型,因为编译器会为我们找出具体的类型。
87、可以显式指定泛型方法的类型,做法是在点操作符与方法名之间插入泛型参数列表。
88、在泛型代码内部,无法获得任何有关泛型参数类型的信息。
89、泛型类型参数将擦除到它的第一个边界,并将类型参数替换为它的擦除。例:List<T>将被擦除为List,普通变量被擦除为Object。
90、在泛型中创建数组推荐使用Array.newInstance()。
91、若泛型代码中需要知道确切类型信息,则必须传入类型的Class对象。若需创建示例对象,推荐使用工厂模式,传入支持泛型的工厂对象。
92、成功创建泛型数组的唯一方式是创建一个被擦除类型的新数组,然后将其转型为泛型数组。实际使用中一般利用List代替数组。
93、实现“枚举的枚举”的方法:在一个enum内部定义接口,接口内定义若干个实现了该接口的enum,外部enum的成员构造器传入接口内部enum对应的class对象。