极客java11

1.try catch finally 语句

  • 异常的处理在有返回值的条件下,返回一个特殊的值代表情况不对
  • 可以认为finally语句会在方法返回后,后面的方法开始前
  • 无论是因为return结束还是因为异常结束,finally都会执行
  • finally里面最后不要有return语句
  • finally里面给return用的变量赋值没有任何作用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
package com.geekboys.exception;

public class TryCatchFinallyAppMain {
private static int VAL = 0;

public static void main(String[] args) {
System.out.println(withFinally());
System.out.println(VAL);

}
private static int withFinally() {
int len = 0;
try {
String s = null;
return s.length();
} catch (Exception ex) {
len = -1;
System.out.println("执行catch里的return");
return len;
} finally {
System.out.println("指向finally语句");
VAL = 999;
// len = 99;
System.out.println("finally语句执行结束");
}
}
}
tyr finally语句
  • finally里面的返回值语句,会打乱exception的传递
  • finally里面给return用的变量赋值没用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package com.geekboys.exception;

public class TryFinallyAppMain {
private static int VAL = 0;
public static void main(String[] args) {
System.out.println(withFinally());
System.out.println(VAL);
}
private static int withFinally() {
int len = 0;
try {
String s = null;
return s.length();
} finally {
System.out.println("执行finally语句");
len = -2;
VAL = 999;
System.out.println("finally语句执行完毕");
return -2;
}
}
}
catch多种异常
1
2
3
4
5
6
7
private static void catchMultiNew() {
try {
throwMultiException(1);
}catch (ClassNotFoundException | IOException ex) {
ex.printStackTrace();
}
}

2.自动回收资源的try语句

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package com.geekboys.exception;

public class TryWithResource {
public static void main(String[] args) {
try ( MyAutoCloseableResource res1 = new MyAutoCloseableResource("res1");
MyAutoCloseableResource res2 = new MyAutoCloseableResource("res2")
) {
while (true) {
System.out.println(res1.read());
System.out.println(res2.read());
}
} catch (Exception e) {
e.printStackTrace();
}
}
}

  • 在try后面小括号中添加实现了 Autoclose的类 ,就会在出现异常的时候自动调close方法

3.Java中常见的异常

1.unchecked

  • NullPointerException
    • 空指针异常
  • IndexOutOfBoundsException
    • 索引越界异常
  • ClassCastException
    • 两种不同的类的引用之间相互赋值 (强转)

2.Checked

  • ClassNotFounException
  • IOException

4.Collection类族简介

  • 数据结构就是组织数据的方式
  • 数组就是一种最基本的数据结构,编程语言本身就支持
  • 计算机中基础的数据结构就是List Set Queue Map,高级一点的有Tree heap,这些数据结构需要代买来实现,这些实现也是一个个类,只是专注的问题更加抽象和通用
  • Collection代表一堆元素,翻译为集合
  • Collection接口的继承者 和他们的实现构成了我们所谓的Collection类族

5.Collection中的List(上)

  • List代表有顺序的一组元素,中文一般翻译为链表
  • List类继承自Collection
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
package com.geekboys.learnlist.mylist;

import java.util.*;

public class MyArrayList implements List {
private Object[] elements;
private int curr;

public MyArrayList() {
this.elements = new Object[16];
curr =0;
}

@Override
public int size() {
return curr;
}

@Override
public boolean isEmpty() {
return curr == 0;
}

@Override
public boolean contains(Object o) {
for (Object ele : elements) {
if (Objects.equals(ele,o)) {
return true;
}
}
return false;
}

@Override
public void clear() {
curr = 0;
}

@Override
public Object get(int index) {
if (index > curr || index < 0) {
throw new IndexOutOfBoundsException("Out of bound"+curr+" for " + index);
}
return elements[index];
}

@Override
public boolean add(Object o) {
if (curr == elements.length-1) {
Object[] temp = new Object[elements.length * 2];
for (int i = 0;i < elements.length;i++) {
temp[i] = elements[i];
}
elements = temp;
}elements[curr] = o;
curr++;
return true;
}
}
  • 自己实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
package com.geekboys.learnlist.mylist;

import java.util.*;

public class MyLinkedList implements List {
static class LinkNode {
LinkNode prev;
LinkNode next;
Object value;

public LinkNode(LinkNode prev, LinkNode next, Object value) {
this.prev = prev;
this.next = next;
this.value = value;
}
}
private LinkNode start = null;
private LinkNode end = null;
private int size = 0;


@Override
public int size() {
return size;
}

@Override
public boolean isEmpty() {
return size == 0;
}

@Override
public boolean contains(Object o) {

LinkNode curr = start;
while (curr != null) {
if (Objects.equals(curr,o)) {
return true;
}
curr = curr.next;
}
return false;

}

@Override
public void clear() {
start = null;
end = null;
size = 0;
}

@Override
public Object get(int index) {
if (index > size || index < 0 ){
throw new IndexOutOfBoundsException("Out of bound");
}
LinkNode curr = start;
for (int i = 0; i < index;i++) {
curr = curr.next;
}
return curr.value;
}


@Override
public boolean add(Object o) {
LinkNode newNode = new LinkNode(end,null,o);
if (start == null) {
start = newNode;
}
if (end != null) {
end.next = newNode;
}
end = newNode;
size++;
return true;
}

7.Collection 中的Set

  • Set代表一个元素不重复的集合,也就是说 ,Set中的元素两两不相等
  • Java中Set的最常用的实现类: HashSet
  • 顾名思义是使用了元素的hash值 做去重
  • hashCode和equals符合这样一个约定:equals返回true,hashcode必须相等。
  • 很多Java类 库 中的代码都是按照这种约定使用这两个方法,比如HashSet。这也就是卫生么我们要求如果 一个类覆盖了hashCode方法 就一定要覆盖equals方法 ,并保证 方法的实现符合上述约定

8.范型简析(下)

  • 泛型的引文名叫做generics,一系列和泛型相关的名词都是以generic为前缀:比如generic Method Generic Types
  • 使用泛型可以让List里面只有一种元素
  • 范型的语法就是在支持范型的类型上,给出类型的定义
  • List接口是支持范型的,类型就是List里允许的元素的类型
  • 创建List实例和引用的时候,都可以指定范型对应的类型
  • 不指定就是Object
  • 在指定为String后,如果尝试增加非String类型的元素,会报错

9.范型简析()

  • 告诉编译器帮我们检查类型是否匹配,类型是什么不重要,一样才重要
  • 在使用的地方悄悄的帮我们做类型的强制转换
  • 对于一个方法来说,我们并没有使用<>来确定类型,在调用方法前接受返回值是啥类型,方法中的范型就是啥类型
  • 使用范型强转报错 实际上是再 调用的地方
  • 如果范型信息缺失了,编译器也无法帮忙检查出类型不匹配只会 给出unchecked警告

10.再探范型

  • 泛型类型不可以调用方法,因为不知道什么类型,如果需要使用某个类的方法,则需要给定类型的范围

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    package com.geekboys.learngenerics.define;

    import com.geekboys.learngenerics.ext.GrandParent;

    public class MyGenericClassBounded<MyType extends GrandParent> {

    private MyType myType;

    public MyGenericClassBounded(MyType myType) {
    this.myType = myType;
    myType.getNum();
    }

    public void setMyType(MyType myType) {
    this.myType = myType;
    }
    }
    范型的深水区:协变与逆变
  • 协变和逆变是范型中比较绕的点,java对协变和逆变的支持是为了支持范围更广的参数类型

  • 协变和逆变是针对引用类型的,可以用在返回值类型,参数类型,等引用类型上。创建对象的时候不能使用协变和逆变

  • 写入使用逆变,读取使用协变

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
package com.geekboys.learngenerics;

import com.geekboys.learngenerics.ext.Children;
import com.geekboys.learngenerics.ext.GrandParent;
import com.geekboys.learngenerics.ext.Parent;

import java.util.ArrayList;
import java.util.List;

public class MoreGenericsAppMain {
public static void main(String[] args) {
List<Children> g3List = new ArrayList<>();
// TODO 范型类型不管继承关系,只管严格的匹配
// TODO 换句话说Child是Parent的子类但是List<Child> 不是
// TODO 那就要让接收方也就是形参,声明为协变范型
extMethod(g3List);
// TODO 同样的道理我们可以声明协变的引用,让它可以接受的List引用的范型类型为Parent或者其子类
List<? extends Parent> g2ListExt = null;
g2ListExt = new ArrayList<Children>();
g2ListExt = new ArrayList<Parent>();
// g2ListExt = new ArrayList<GrandParent>();
// TODO 但是如果是带协变的引用,我们无法让具体的类型满足其参数要求
// g2ListExt.add(new Children());
// g2ListExt.add(new Parent());
// g2ListExt.add(new GrandParent());
// TODO 原因是如果Java允许了,那么就会造成潜在的错误
List<Children> g3OnlyList = new ArrayList<>();
g2ListExt = g3OnlyList;
// TODO 如果允许add一个Parent的对象就代表什么呢
// g2ListExt.add(new Parent());
// TODO 那就代表着,原本只因该有child或者其子类的引用指向的对象,结果通过

// TODO 除了协变,Java还有逆变
// TODO 逆变和协变正好相反,允许的类型为Parent或者其父类
List<? super Parent> g2ListSup = null;
// g2ListSup = new ArrayList<Children>();
g2ListSup = new ArrayList<Parent>();
g2ListSup = new ArrayList<GrandParent>();
// TODO 但是同样的原因,无法让具体的类型 满足其要求
// g2ListSup.add(new GrandParent());
// g2ListSup.add(new Parent());
// g2ListSup.add(new Children());
// TODO 无论是协变还是逆变,都只能用在引用上,而不能在创建对象时使用其作为范型参数
// List<? extends Parent> gListExt = new ArrayList<? extends Parent>();
// List<? super Parent> gListSup = new ArrayList<? super Parent>();

}
// TODO 协变语法如下,就是这个参数可以接受的List引用的范型类型为Parent或者其子类
public static void extMethod(List<? extends Parent> extParam) {}

public static void justG2Method(List<Parent> extParam) {}

public static void supMethod(List<? super Parent> extParam) {}

}
你的支持是我最大的动力!
0%