JavaSE进阶
JavaSE进阶1 Java常用类1.1 Date 类1.2 Properties 类2 Java Lamda表达式3 Java 正则表达式3.1 正则表达式概述3.2 正则表达式匹配使用3.3 正则表达式语法4 Java 文件,流,IO4.1 读写文件5 Java数据结构5.1 Vector 类5.2 Stack 类5.3 Java 集合框架5.4 ArrayList类5.5 LinkedList类5.6 HashSet类5.7 HashMap类5.8 Iterator迭代器6 Java泛型6.1 概述6.2 泛型类6.3 泛型接口6.4 泛型通配符6.5 泛型方法6.6 泛型边界7 Java序列化7.1 序列化对象
JavaSE进阶
1 Java常用类
1.1 Date 类
获取当前的日期时间
x1// 初始化 Date 对象
2Date date = new Date();
3
4// 使用 toString() 函数显示日期时间
5System.out.println(date.toString());
SimpleDateFormat 格式化日期
xxxxxxxxxx
51Date dNow = new Date( );
2//确定转换的格式
3SimpleDateFormat ft = new SimpleDateFormat ("yyyy-MM-dd hh:mm:ss");
4
5System.out.println("当前时间为: " + ft.format(dNow));
- 其中 yyyy 是完整的公元年,MM 是月份,dd 是日期,HH:mm:ss 是时、分、秒。
- 注意:有的格式大写,有的格式小写,例如 MM 是月份,mm 是分;HH 是 24 小时制,而 hh 是 12 小时制。
xxxxxxxxxx
11Thu 2021.12.02 at 10:11:02 AM UTC
printf格式化日期
通过转换符输出不同格式的时间
xxxxxxxxxx
191public class DateDemo {
2 public static void main(String[] args) {
3 // 初始化 Date 对象
4 Date date = new Date();
5
6 //c的使用
7 System.out.printf("全部日期和时间信息:%tc%n",date);
8 //f的使用
9 System.out.printf("年-月-日格式:%tF%n",date);
10 //d的使用
11 System.out.printf("月/日/年格式:%tD%n",date);
12 //r的使用
13 System.out.printf("HH:MM:SS PM格式(12时制):%tr%n",date);
14 //t的使用
15 System.out.printf("HH:MM:SS格式(24时制):%tT%n",date);
16 //R的使用
17 System.out.printf("HH:MM格式(24时制):%tR",date);
18 }
19}
1.2 Properties 类
.properties文件以key=value方式储存数据, Properties 类load方法接受文件输入流,用key值查找value
实例:
xxxxxxxxxx
31url=localhost:3306
2username=root
3password=123456
xxxxxxxxxx
121public static void main(String[] args) {
2 try {
3 InputStream testConfig = TestProperties.class.getClassLoader().getResourceAsStream("IOStream/test.properties");
4 Properties config = new Properties();
5 config.load(testConfig);
6 System.out.println(config.getProperty("url"));
7 System.out.println(config.getProperty("username"));
8 System.out.println(config.getProperty("password"));
9 } catch (IOException e) {
10 e.printStackTrace();
11 }
12}
2 Java Lamda表达式
xxxxxxxxxx
101/*定义一个函数式接口
2* 函数式接口:只包唯一个抽象方法*/
3interface ILike{
4 void lambda();
5}
6
7/*Lambda表达式*/
8ILike like5 = () ->{
9 System.out.println("I Like Lambda5");
10};
xxxxxxxxxx
101/*多行代码需要加代码块
2* 参数类型可以去掉,多个参数需要需要加括号
3* (参数)->{重写方法}
4*/
5Love love = a -> System.out.println("i love lambda"+a);
6love.lambda(520);
7
8interface Love {
9 void lambda(int a);
10}
3 Java 正则表达式
3.1 正则表达式概述
正则表达式 | 描述 |
---|---|
this is text | 匹配字符串 "this is text" |
this\s+is\s+text | 注意字符串中的 \s+。 匹配单词 "this" 后面的 \s+ 可以匹配多个空格,之后匹配 is 字符串,再之后 \s+ 匹配多个空格然后再跟上 text 字符串。 可以匹配这个实例:this is text |
^\d+(.\d+)? | ^ 定义了以什么开始 \d+ 匹配一个或多个数字 ? 设置括号内的选项是可选的 . 匹配 "." 可以匹配的实例:"5", "1.5" 和 "2.21"。 |
Pattern 类:
pattern 对象是一个正则表达式的编译表示。Pattern 类没有公共构造方法。要创建一个 Pattern 对象,你必须首先调用其公共静态编译方法,它返回一个 Pattern 对象。该方法接受一个正则表达式作为它的第一个参数。
Matcher 类:
Matcher 对象是对输入字符串进行解释和匹配操作的引擎。与Pattern 类一样,Matcher 也没有公共构造方法。你需要调用 Pattern 对象的 matcher 方法来获得一个 Matcher 对象。
PatternSyntaxException:
PatternSyntaxException 是一个非强制异常类,它表示一个正则表达式模式中的语法错误。
3.2 正则表达式匹配使用
Pattern 类的使用:
xxxxxxxxxx
101public class TestPattern {
2 public static void main(String[] args) {
3 String email = "123@qq.com";
4
5 String pattern = "(\\w+)@(\\w+)\\.com";
6
7 boolean isMatch = Pattern.matches(pattern,email);
8 System.out.println("邮箱地址是否合法: " + isMatch);
9 }
10}
捕获组
(A)(B)分为了三个组:
- (A)(B)
- (A)
- (B)
xxxxxxxxxx
161public static void main(String[] args) {
2 String email = "123@qq.com";
3
4 String pattern = "(\\w+)@(\\w+)\\.com";
5 //创建 Pattern 对象
6 Pattern p = Pattern.compile(pattern);
7 //创建 matcher 对象
8 Matcher m = p.matcher(email);
9 if (m.find( )) {
10 System.out.println("Found value: " + m.group(0) );
11 System.out.println("Found value: " + m.group(1) );
12 System.out.println("Found value: " + m.group(2) );
13 } else {
14 System.out.println("NO MATCH");
15 }
16}
结果:
xxxxxxxxxx
31Found value: 123@qq.com
2Found value: 123
3Found value: qq
3.3 正则表达式语法
在 Java 中,\ 表示:我要插入一个正则表达式的反斜线,所以其后的字符具有特殊的意义
所以Java的正则表达式转义字符需要两个""
字符 | 说明 |
---|---|
\ | 将下一字符标记为特殊字符、文本、反向引用或八进制转义符。例如, n匹配字符 n。\n 匹配换行符。序列 \\ 匹配 \ ,\( 匹配 (。 |
^ | 匹配输入字符串开始的位置。如果设置了 RegExp 对象的 Multiline 属性,^ 还会与"\n"或"\r"之后的位置匹配。 |
$ | 匹配输入字符串结尾的位置。如果设置了 RegExp 对象的 Multiline 属性,$ 还会与"\n"或"\r"之前的位置匹配。 |
* | 零次或多次匹配前面的字符或子表达式。例如,zo* 匹配"z"和"zoo"。* 等效于 {0,}。 |
+ | 一次或多次匹配前面的字符或子表达式。例如,"zo+"与"zo"和"zoo"匹配,但与"z"不匹配。+ 等效于 {1,}。 |
? | 零次或一次匹配前面的字符或子表达式。例如,"do(es)?"匹配"do"或"does"中的"do"。? 等效于 {0,1}。 |
{n} | n 是非负整数。正好匹配 n 次。例如,"o{2}"与"Bob"中的"o"不匹配,但与"food"中的两个"o"匹配。 |
{n,} | n 是非负整数。至少匹配 n 次。例如,"o{2,}"不匹配"Bob"中的"o",而匹配"foooood"中的所有 o。"o{1,}"等效于"o+"。"o{0,}"等效于"o*"。 |
{n,m} | m 和 n 是非负整数,其中 n <= m。匹配至少 n 次,至多 m 次。例如,"o{1,3}"匹配"fooooood"中的头三个 o。'o{0,1}' 等效于 'o?'。注意:您不能将空格插入逗号和数字之间。 |
? | 当此字符紧随任何其他限定符(、+、?、{n}、{n,}、{n,m*})之后时,匹配模式是"非贪心的"。"非贪心的"模式匹配搜索到的、尽可能短的字符串,而默认的"贪心的"模式匹配搜索到的、尽可能长的字符串。例如,在字符串"oooo"中,"o+?"只匹配单个"o",而"o+"匹配所有"o"。 |
. | 匹配除"\r\n"之外的任何单个字符。若要匹配包括"\r\n"在内的任意字符,请使用诸如"[\s\S]"之类的模式。 |
(pattern) | 匹配 pattern 并捕获该匹配的子表达式。可以使用 |
(?:pattern) | 匹配 pattern 但不捕获该匹配的子表达式,即它是一个非捕获匹配,不存储供以后使用的匹配。这对于用"or"字符 (|) 组合模式部件的情况很有用。例如,'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"。预测先行不占用字符,即发生匹配后,下一匹配的搜索紧随上一匹配之后,而不是在组成预测先行的字符后。 |
x|y | 匹配 x 或 y。例如,'z|food' 匹配"z"或"food"。'(z|f)ood' 匹配"zood"或"food"。 |
[xyz] | 字符集。匹配包含的任一字符。例如,"[abc]"匹配"plain"中的"a"。 |
[^xyz] | 反向字符集。匹配未包含的任何字符。例如,"[^abc]"匹配"plain"中"p","l","i","n"。 |
[a-z] | 字符范围。匹配指定范围内的任何字符。例如,"[a-z]"匹配"a"到"z"范围内的任何小写字母。 |
[^a-z] | 反向范围字符。匹配不在指定的范围内的任何字符。例如,"[^a-z]"匹配任何不在"a"到"z"范围内的任何字符。 |
\b | 匹配一个字边界,即字与空格间的位置。例如,"er\b"匹配"never"中的"er",但不匹配"verb"中的"er"。 |
\B | 非字边界匹配。"er\B"匹配"verb"中的"er",但不匹配"never"中的"er"。 |
\cx | 匹配 x 指示的控制字符。例如,\cM 匹配 Control-M 或回车符。x 的值必须在 A-Z 或 a-z 之间。如果不是这样,则假定 c 就是"c"字符本身。 |
\d | 数字字符匹配。等效于 [0-9]。 |
\D | 非数字字符匹配。等效于 [^0-9]。 |
\f | 换页符匹配。等效于 \x0c 和 \cL。 |
\n | 换行符匹配。等效于 \x0a 和 \cJ。 |
\r | 匹配一个回车符。等效于 \x0d 和 \cM。 |
\s | 匹配任何空白字符,包括空格、制表符、换页符等。与 [ \f\n\r\t\v] 等效。 |
\S | 匹配任何非空白字符。与 [^ \f\n\r\t\v] 等效。 |
\t | 制表符匹配。与 \x09 和 \cI 等效。 |
\v | 垂直制表符匹配。与 \x0b 和 \cK 等效。 |
\w | 匹配任何字类字符,包括下划线。与"[A-Za-z0-9_]"等效。 |
\W | 与任何非单词字符匹配。与"[^A-Za-z0-9_]等效。 |
\xn | 匹配 n,此处的 n 是一个十六进制转义码。十六进制转义码必须正好是两位数长。例如,"\x41"匹配"A"。"\x041"与"\x04"&"1"等效。允许在正则表达式中使用 ASCII 代码。 |
*num* | 匹配 num,此处的 num 是一个正整数。到捕获匹配的反向引用。例如,"(.)\1"匹配两个连续的相同字符。 |
*n* | 标识一个八进制转义码或反向引用。如果 *n* 前面至少有 n 个捕获子表达式,那么 n 是反向引用。否则,如果 n 是八进制数 (0-7),那么 n 是八进制转义码。 |
*nm* | 标识一个八进制转义码或反向引用。如果 *nm* 前面至少有 nm 个捕获子表达式,那么 nm 是反向引用。如果 *nm* 前面至少有 n 个捕获,则 n 是反向引用,后面跟有字符 m。如果两种前面的情况都不存在,则 *nm* 匹配八进制值 nm,其中 n 和 m 是八进制数字 (0-7)。 |
\nml | 当 n 是八进制数 (0-3),m 和 l 是八进制数 (0-7) 时,匹配八进制转义码 nml。 |
\un | 匹配 n,其中 n 是以四位十六进制数表示的 Unicode 字符。例如,\u00A9 匹配版权符号 (©)。 |
来自 菜鸟教程
4 Java 文件,流,IO
4.1 读写文件
getResourceAsStream获取InputStream
1.通过class对象获取 path不以'/'开头在此类包下,以'/'开头在根目录下
xxxxxxxxxx
11Class.getResourceAsStream(String path)
2.通过ClassLoader获取 path不以'/'开头在根目录下,以'/'开头在此类包下
xxxxxxxxxx
11Class.getClassLoader.getResourceAsStream(String path)
FileInputStream
1.File类对象创建FileInputStream流对象
xxxxxxxxxx
11public FileInputStream(File file) throws FileNotFoundException{}
2.文件路径创建FileInputStream流对象
xxxxxxxxxx
11public FileInputStream(String name) throws FileNotFoundException
FileInputStream测试:
xxxxxxxxxx
131public class TestFileInputStream {
2 public static void main(String[] args) {
3 File file = new File("test.txt");
4
5 try {
6 FileInputStream in = new FileInputStream(file);
7 } catch (FileNotFoundException e) {
8 //文件未找到
9 System.out.println("文件未找到");
10 e.printStackTrace();
11 }
12 }
13}
read方法
从输入流中读取一个字节返回int型变量,若到达文件末尾,则返回-1
xxxxxxxxxx
11public int read() throws IOException
从输入流中读取b.length个字节到字节数组中,返回读入缓冲区的总字节数,若到达文件末尾,则返回-1
xxxxxxxxxx
11public int read(byte[] b) throws IOException
文件读取测试
xxxxxxxxxx
281public static void main(String[] args) {
2 File file = new File("baseGrammar/src/IOStream/test.txt");
3
4 try {
5 FileInputStream in = new FileInputStream(file);
6 StringBuffer buffer = new StringBuffer();
7 int n = 0;
8 while (n != -1){
9 n = in.read();
10 if (n == -1){
11 break;
12 }
13 char by = (char) n;
14 buffer.append(by);
15 }
16 System.out.println(buffer);
17 System.out.println("文件读取完毕");
18
19 } catch (FileNotFoundException e) {
20 //文件未找到
21 System.out.println("文件未找到");
22 e.printStackTrace();
23 } catch (IOException e) {
24 //文件读取异常
25 System.out.println("文件读取异常");
26 e.printStackTrace();
27 }
28}
FileOutputStream
创建FileOutputStream流以写入数据到File对象所代表的文件
xxxxxxxxxx
11public FileOutputStream(File file) throws FileNotFoundException{}
FileOutputStream测试:
xxxxxxxxxx
131public class TestFileOutputStream {
2 public static void main(String[] args) {
3 File file = new File("test.txt");
4
5 try {
6 FileOutputStream out = new FileOutputStream(file);
7 } catch (FileNotFoundException e) {
8 //文件未找到
9 System.out.println("文件未找到");
10 e.printStackTrace();
11 }
12 }
13}
write方法
xxxxxxxxxx
11public void write(byte b[]) throws IOException
文件写入测试:
- FileOutputStream true 在文件后面追加,false 覆盖写入
xxxxxxxxxx
201public class TestFileOutputStream {
2 public static void main(String[] args) {
3 File file = new File("baseGrammar/src/IOStream/test.txt");
4
5 try {
6 String content = "Hello,world! \n file write";
7 FileOutputStream out = new FileOutputStream(file,true);
8 out.write(content.getBytes());
9 System.out.println("写入成功");
10 } catch (FileNotFoundException e) {
11 //文件未找到
12 System.out.println("文件未找到");
13 e.printStackTrace();
14 } catch (IOException e) {
15 //文件写入失败
16 System.out.println("文件写入失败");
17 e.printStackTrace();
18 }
19 }
20}
5 Java数据结构
5.1 Vector 类
Vector 类实现了一个动态数组,和 ArrayList 很相似,但是两者是不同的:
- Vector 是同步访问的。
- Vector 包含了许多传统的方法,这些方法不属于集合框架。
Vector 类支持 4 种构造方法:
- 第一种 构造方法创建一个默认的向量,默认大小为 10:
xxxxxxxxxx
11Vector()
- 第二种 构造方法创建指定大小的向量。
xxxxxxxxxx
11Vector(int size)
- 第三种 构造方法创建指定大小的向量,并且增量用 incr 指定。增量表示向量每次增加的元素数目。
xxxxxxxxxx
11Vector(int size,int incr)
- 第四种 构造方法创建一个包含集合 c 元素的向量:
xxxxxxxxxx
11Vector(Collection c)
Vector使用:
xxxxxxxxxx
221public class TestVector {
2 public static void main(String[] args) {
3 Vector v = new Vector(3,2);
4 System.out.println("当前容器容量:"+v.capacity());
5 v.addElement(new Integer(1));
6 v.addElement(new Integer(2));
7 v.addElement(new Integer(3));
8 v.addElement(new Integer(4));
9 v.addElement(new Integer(5));
10 System.out.println("添加元素后容器容量:"+v.capacity());
11 v.addElement(new Double(6.6));
12 v.addElement(new Float(7.7));
13 System.out.println("添加元素后容器容量:"+v.capacity());
14 System.out.println("第一个元素:"+v.firstElement());
15 System.out.println("最后一个元素:"+v.lastElement());
16 Enumeration elements = v.elements();
17 while (elements.hasMoreElements()){
18 System.out.print(elements.nextElement()+" ");
19 }
20 System.out.println();
21 }
22}
5.2 Stack 类
栈是Vector的一个子类,它实现了一个标准的后进先出的栈
xxxxxxxxxx
11Stack()
Stack使用:
xxxxxxxxxx
311public class TestStack {
2 static void showPush(Stack<Integer> stack, int a) {
3 stack.push(new Integer(a));
4 System.out.println("push <- " + a);
5 System.out.println("stack: " + stack);
6 }
7
8 static void showPop(Stack<Integer> stack) {
9 System.out.print("pop -> ");
10 Integer a = (Integer) stack.pop();
11 System.out.println(a);
12 System.out.println("stack: " + stack);
13 }
14
15 public static void main(String args[]) {
16 Stack<Integer> stack = new Stack<Integer>();
17 System.out.println("stack: " + stack);
18 showPush(stack, 11);
19 showPush(stack, 22);
20 showPush(stack, 33);
21 showPop(stack);
22 showPop(stack);
23 showPop(stack);
24 try {
25 //检查栈是否为空
26 showPop(stack);
27 } catch (EmptyStackException e) {
28 System.out.println("empty stack");
29 }
30 }
31}
5.3 Java 集合框架
- 集合框架高效地实现了基本的数据结构(集合)
- 允许不同类型的集合,以类似的方式工作,具有高度的互操作性
Set和List的区别
- Set 接口实例存储的是无序的,不重复的数据。List 接口实例存储的是有序的,可以重复的元素。
- Set检索效率低下,删除和插入效率高,插入和删除不会引起元素位置改变 实现类有HashSet,TreeSet。
- List和数组类似,可以动态增长,根据实际存储的数据的长度自动增长List的长度。查找元素效率高,插入删除效率低,因为会引起其他元素位置改变 实现类有ArrayList,LinkedList,Vector 。
迭代器:Iterator
5.4 ArrayList类
初始化
xxxxxxxxxx
11ArrayList<E> objectName =new ArrayList<>();
add方法
xxxxxxxxxx
91public static void main(String[] args) {
2 ArrayList<String> list = new ArrayList<String>();
3 //add() 方法添加元素
4 list.add("XiaoMing");
5 list.add("ZhangSan");
6 list.add("LiSi");
7 list.add("LiHua");
8 System.out.println(list);
9}
get方法
xxxxxxxxxx
21//get() 方法获取元素
2System.out.println(list.get(2));
set方法
xxxxxxxxxx
21//set() 方法修改元素
2list.set(2,"LiMing");
remove方法
xxxxxxxxxx
21//remove() 方法删除元素
2list.remove(2);
size方法
xxxxxxxxxx
21//size() 获取大小
2list.size()
Collections.sort排序
xxxxxxxxxx
11Collections.sort(list);
5.5 LinkedList类
比较:
ArrayList:数组
- 适合频繁查找
- 只在末尾添加删除元素
LinkedList:链表
- 通过循环迭代访问元素
- 频繁在中间删除,插入元素
LinkedList使用
xxxxxxxxxx
241public static void main(String[] args) {
2 LinkedList<String> list = new LinkedList<String>();
3 //add() 方法添加元素
4 list.add("XiaoMing");
5 list.add("ZhangSan");
6 list.add("LiSi");
7 list.add("LiHua");
8 System.out.println(list);
9 //get() 方法获取元素
10 System.out.println(list.get(2));
11 //set() 方法修改元素
12 list.set(2,"LiMing");
13 System.out.println(list);
14 //remove() 方法删除元素
15 list.remove(2);
16 System.out.println(list);
17 System.out.println(list.size());
18 //foreach获取元素
19 for (String s : list) {
20 System.out.println(s);
21 }
22 Collections.sort(list);
23 System.out.println(list);
24}
5.6 HashSet类
- HashSet 基于 HashMap 来实现的,是一个不允许有重复元素的集合。
- HashSet 允许有 null 值。
- HashSet 是无序的,即不会记录插入的顺序。
- HashSet 不是线程安全的, 如果多个线程尝试同时修改 HashSet,则最终结果是不确定的。 您必须在多线程访问时显式同步对 HashSet 的并发访问。
HashSet使用:
xxxxxxxxxx
211public static void main(String[] args) {
2 HashSet<String> hashSet = new HashSet<String>();
3 //add() 方法添加元素
4 hashSet.add("XiaoMing");
5 hashSet.add("ZhangSan");
6 hashSet.add("LiSi");
7 hashSet.add("LiHua");
8 hashSet.add("LiHua");//重复不会插入
9 System.out.println(hashSet);
10 //remove() 方法删除元素
11 hashSet.remove("LiSi");
12 System.out.println(hashSet);
13 System.out.println(hashSet.size());
14 //
15 System.out.println(hashSet.contains("XiaoMing"));
16 //foreach获取元素
17 for (String s : hashSet) {
18 System.out.println(s);
19 }
20 System.out.println(hashSet);
21}
5.7 HashMap类
- HashMap 是一个散列表,它存储的内容是键值对(key-value)映射。
- HashMap 实现了 Map 接口,根据键的 HashCode 值存储数据,具有很快的访问速度,最多允许一条记录的键为 null,不支持线程同步。
- HashMap 是无序的,即不会记录插入的顺序。
初始化
xxxxxxxxxx
11HashMap<Integer, String> Sites = new HashMap<Integer, String>();
HashMap使用:
xxxxxxxxxx
211public static void main(String[] args) {
2 HashMap<String,String> map = new HashMap<String,String>();
3 //put() 添加元素
4 map.put("name","LiHua");
5 map.put("sex","nan");
6 map.put("class","one");
7 map.put("email","123@qq.com");
8 System.out.println(map);
9 System.out.println(map.get("email"));
10 map.remove("class");
11 System.out.println(map);
12 System.out.println(map.size());
13
14 for (String s : map.keySet()) {
15 System.out.println("key: "+s+" value: "+map.get(s));
16 }
17
18 for (String value : map.values()) {
19 System.out.println(value);
20 }
21}
5.8 Iterator迭代器
Iterator迭代器是一种用于访问集合的方法,可用于迭代 ArrayList和 HashSet等集合。
迭代器使用:
xxxxxxxxxx
311public static void main(String[] args) {
2 ArrayList<String> list = new ArrayList<String>();
3 //add() 方法添加元素
4 list.add("XiaoMing");
5 list.add("ZhangSan");
6 list.add("LiSi");
7 list.add("LiHua");
8 // 获取迭代器
9 Iterator<String> it = list.iterator();
10
11 // 输出集合中的所有元素
12 while(it.hasNext()) {
13 System.out.println(it.next());
14 }
15
16 ArrayList<Integer> list1 = new ArrayList<Integer>();
17 list1.add(1);
18 list1.add(3);
19 list1.add(5);
20 list1.add(8);
21 // 获取迭代器
22 Iterator<Integer> it1 = list1.iterator();
23
24 //删除大于5的元素
25 while (it1.hasNext()){
26 if (it1.next()>5){
27 it1.remove();
28 }
29 }
30 System.out.println(list1);
31}
6 Java泛型
6.1 概述
- 泛型,即“参数化类型”,将类型由原来的具体的类型参数化,类似于方法中的变量参数,此时类型也定义成参数形式(可以称之为类型形参),然后在使用/调用时传入具体的类型(类型实参)。(把类型作为参数)
- 泛型的本质是为了参数化类型(在不创建新的类型的情况下,通过泛型指定的不同类型来控制形参具体限制的类型)。也就是说在泛型使用过程中,操作的数据类型被指定为一个参数,这种参数类型可以用在类、接口和方法中,分别被称为泛型类、泛型接口、泛型方法。
xxxxxxxxxx
71List arrayList = new ArrayList();
2arrayList.add("a");
3arrayList.add(10);
4
5for(int i = 0; i< arrayList.size();i++){
6 String item = (String)arrayList.get(i);
7}
ArrayList可以存放任意类型,使用时都以String的方式使用,导致程序崩溃
泛型只在编译阶段有效
6.2 泛型类
泛型类有:List、Set、Map
基本写法:
xxxxxxxxxx
61class 类名称 <泛型标识:可以随便写任意标识号,标识指定的泛型的类型>{
2 private 泛型标识 /*(成员变量类型)*/ var;
3 .....
4
5 }
6}
泛型类:
xxxxxxxxxx
131//在实例化泛型类时,必须指定T的具体类型
2public class Generic<T>{
3 //key这个成员变量的类型为T,T的类型由外部指定
4 private T key;
5
6 public Generic(T key) { //泛型构造方法形参key的类型也为T,T的类型由外部指定
7 this.key = key;
8 }
9
10 public T getKey(){ //泛型方法getKey的返回值类型为T,T的类型由外部指定
11 return key;
12 }
13}
传入泛型实参创建对象:
xxxxxxxxxx
81//传入的实参类型需与泛型的类型参数类型相同,即为Integer.
2Generic<Integer> genericInteger = new Generic<Integer>(123);
3
4//传入的实参类型需与泛型的类型参数类型相同,即为String.
5Generic<String> genericString = new Generic<String>("value");
6
7System.out.println(genericString.getKey());
8System.out.println(genericInteger.getKey());
如果不传入泛型类型实参的话,在泛型类中使用泛型的方法或成员变量定义的类型可以为任何的类型
6.3 泛型接口
泛型接口与泛型类的定义及使用基本相同:
xxxxxxxxxx
41//定义一个泛型接口
2public interface Generator<T> {
3 public T next();
4}
未传入泛型实参
xxxxxxxxxx
61class FruitGenerator<T> implements Generator<T>{
2
3 public T next() {
4 return null;
5 }
6}
传入泛型实参
xxxxxxxxxx
101public class FruitGenerator implements Generator<String> {
2
3 private String[] fruits = new String[]{"Apple", "Banana", "Pear"};
4
5
6 public String next() {
7 Random rand = new Random();
8 return fruits[rand.nextInt(3)];
9 }
10}
6.4 泛型通配符
xxxxxxxxxx
141Generic<Integer> gInteger = new Generic<Integer>(123);
2Generic<Number> gNumber = new Generic<Number>(456);
3
4showKeyValue(gNumber);
5showKeyValue(gInteger);
6
7//public void showKeyValue1(Generic<Number> obj){
8// System.out.println(obj.getKey());
9//} 在传入gInteger会报错
10
11//在具体类型不确定的时候使用泛型通配符
12public void showKeyValue1(Generic<?> obj){
13 System.out.println(obj.getKey());
14}
6.5 泛型方法
之前泛型类中的方法是使用了类定义的泛型,这里泛型方法指的是方法定义泛型
xxxxxxxxxx
101/*
2 * 泛型方法
3 * @param tClass 传入的泛型实参
4 * @return T 返回值为T类型
5*/
6public <T> T genericMethod(Generic<T> generic)throws InstantiationException ,
7 IllegalAccessException{
8 T t = generic.getKey();
9 return t;
10}
6.6 泛型边界
泛型限制:传入的类型实参必须是指定类型的子类型
xxxxxxxxxx
31public void showKeyValue1(Generic<? extends Number> obj){
2 System.out.println(obj.getKey());
3}
7 Java序列化
将一个对象表示为一个字节序列,将序列化对象写入文件之后,可以从文件中读取出来,并且对它进行反序列化,也就是说,对象的类型信息、对象的数据,还有对象中的数据类型可以用来在内存中新建对象
序列化一个对象,并将它发送到输出流
xxxxxxxxxx
11public final void writeObject(Object x) throws IOException
流中取出下一个对象,并将对象反序列化,返回值为Object
xxxxxxxxxx
11public final Object readObject() throws IOException, ClassNotFoundException
7.1 序列化对象
序列化对象
- 该类必须实现 java.io.Serializable 接口
- 该类的所有属性必须是可序列化的,如果有一个属性不是可序列化的,则该属性必须注明是短暂的
对象创建:
xxxxxxxxxx
111class Employee implements java.io.Serializable
2{
3 public String name;
4 public String address;
5 public transient int SSN;
6 public int number;
7 public void mailCheck()
8 {
9 System.out.println("name: "+ name + " address:" + address);
10 }
11}
序列化:
xxxxxxxxxx
171public static void main(String[] args) {
2 Employee e = new Employee();
3 e.name = "ZhangSan";
4 e.address = "China";
5 e.SSN = 123456;
6 e.number = 111;
7 try {
8 FileOutputStream fileOut = new FileOutputStream("baseGrammar/src/Serialize/employee.ser");
9 ObjectOutputStream objOut = new ObjectOutputStream(fileOut);
10 objOut.writeObject(e);
11 objOut.close();
12 fileOut.close();
13 System.out.println("写入成功");
14 } catch (IOException exc) {
15 exc.printStackTrace();
16 }
17}
反序列化:
xxxxxxxxxx
281public static void main(String[] args) {
2 Employee e = null;
3 FileInputStream fileIn = null;
4 ObjectInputStream objIn = null;
5 try {
6 fileIn = new FileInputStream("baseGrammar/src/Serialize/employee.ser");
7 objIn = new ObjectInputStream(fileIn);
8 e = (Employee) objIn.readObject();
9 } catch (FileNotFoundException exc) {
10 System.out.println("文件未找到");
11 exc.printStackTrace();
12 } catch (IOException exc) {
13 exc.printStackTrace();
14 } catch (ClassNotFoundException exc) {
15 exc.printStackTrace();
16 } finally {
17 try {
18 objIn.close();
19 fileIn.close();
20 } catch (IOException ioException) {
21 ioException.printStackTrace();
22 }
23 }
24 System.out.println(e);
25 e.mailCheck();
26 System.out.println("number: "+e.number);
27 System.out.println("SSN: "+e.SSN);
28}
posted on 2021-12-03 18:11 Egoistic_Flowers 阅读(46) 评论(0) 编辑 收藏 举报