泛型
-
使用泛型
-
代码简写
编译器看到
List<Number>可以自动推断后面的泛型类型List<Number> list = new ArrayList<>();知识补充:
- 为什么用
List list = new ArrayList()而不直接ArrayList?- 依赖于抽象不依赖于实现。 2. 提高灵活性(如改LinkedList,只需改一行代码)
- 向上转型后对方法、变量的使用
- 调用子类同名方法时,使用子类方法
- 不能直接调用子类独有方法,只能使用自己的内部方法
- 父类中的变量无法被子类覆盖或重写
- 可以通过向下转型来调用子类特有的方法和变量
- 为什么用
-
泛型接口
public interface Comparable<T> { int compareTo(T o); } -
静态泛型方法
public class Pair<T> { public static <K> Pair<K> create(K first, K last) { return new Pair<K>(first, last); } }
-
-
擦拭法
虚拟机对泛型一无所知,所有的工作都是编译器做的。
- 编译器把
<T>视为Object - 编译器根据
<T>实现安全的强制转型
- Java泛型局限:
<T>不能是基本类型,例如int,因为实际类型是Object,Object类型无法持有基本类型- 无法取得带泛型的
Class - 无法判断带泛型的
Class
- 编译器把
-
extends通配符
首先,
Pair<Integer>不是Pair<Number>的子类,但是可以通过Pair<? extends Number>使得方法接收所有泛型类型为Number或Number子类的Pair类型public class Main { public static void main(String[] args) { Pair<Integer> p = new Pair<>(123, 456); int n = add(p); System.out.println(n); } static int add(Pair<? extends Number> p) { Number first = p.getFirst(); Number last = p.getLast(); return first.intValue() + last.intValue(); } }-
限制T类型
public class Pair<T extends Number> {}则只能定义:
Pair<Number> p1 = null; Pair<Integer> p2 = new Pair<>(1, 2); Pair<Double> p3 = null; -
允许调用方法
T get()
-
-
super通配符
Pair<? super Integer>表示,方法参数接受所有泛型类型为Integer或Integer父类的Pair类型。-
允许调用方法
set(T) -
PECS原则: Producer Extends Consumer Super
-
无限定通配符
因为
<?>通配符既没有extends,也没有super,因此:- 不允许调用
set(T)方法并传入引用(null除外); - 不允许调用
T get()方法并获取T引用(只能获取Object引用)。
- 不允许调用
-
正则表达式
-
匹配规则
单个字符的匹配规则如下:
正则表达式 规则 可以匹配 A指定字符 A\u548c指定Unicode字符 和.任意字符 a,b,&,0\d数字0~9 0~9\w大小写字母,数字和下划线 a~z,A~Z,0~9,_\s空格、Tab键 空格,Tab \D非数字 a,A,&,_,……\W非\w &,@,中,……\S非\s a,A,&,_,……多个字符的匹配规则如下:
正则表达式 规则 可以匹配 A*任意个数字符 空, A,AA,AAA,……A+至少1个字符 A,AA,AAA,……A?0个或1个字符 空, AA{3}指定个数字符 AAAA{2,3}指定范围个数字符 AA,AAAA{2,}至少n个字符 AA,AAA,AAAA,……A{0,3}最多n个字符 空, A,AA,AAA复杂匹配规则主要有:
正则表达式 规则 可以匹配 ^ 开头 字符串开头 $ 结尾 字符串结束 [ABC] […]内任意字符 A,B,C [A-F0-9xy] 指定范围的字符 A,……,F,0,……,9,x,y[^A-F] 指定范围外的任意字符 非 A~FAB|CD|EF AB或CD或EF AB,CD,EF -
分组匹配
按括号提取子串:引入
java.util.regex,用Pattern对象匹配,匹配后获得一个Matcher对象,如果匹配成功可以直接从Matcher.group(index)返回子串。public class Main { public static void main(String[] args) { Pattern p = Pattern.compile("(\\d{3,4})\\-(\\d{7,8})"); Matcher m = p.matcher("010-12345678"); if (m.matches()) { String g0 = m.group(0); // 010-12345678 String g1 = m.group(1); // 010 String g2 = m.group(2); // 12345678 } else { System.out.println("匹配失败!"); } } } -
非贪婪匹配
贪婪匹配:任何一个规则,它总是尽可能多地向后匹配
非贪婪匹配:尽可能少的匹配,使用
?如:正则表达式:
(\d+)(0*),将"123000"提取为"123000"和"" 正则表达式:
(\d+?)(0*),将"123000"提取为"123"和"000" -
搜索和替换
-
分割字符串
"a b c".split("\\s"); // { "a", "b", "c" } "a b c".split("\\s"); // { "a", "b", "", "c" } "a, b ;; c".split("[\\,\\;\\s]+"); // { "a", "b", "c" } -
搜索字符串(
matcher.find())public class Main { public static void main(String[] args) { String s = "the quick brown fox jumps over the lazy dog."; Pattern p = Pattern.compile("\\wo\\w"); Matcher m = p.matcher(s); while (m.find()) { String sub = s.substring(m.start(), m.end()); System.out.println(sub); } } } // row fox dog -
反向引用
使用
replaceAll()的时候,我们传入的第二个参数可以使用$1、$2来反向引用匹配到的子串。例如:public class Main { public static void main(String[] args) { String s = "the quick brown fox jumps over the lazy dog."; String r = s.replaceAll("\\s([a-z]{4})\\s([a-z]{3})", " <b>$1</b>$2 "); System.out.println(r); } } // the quick brown fox jumps <b>over</b>the <b>lazy</b>dog .
-