1.lambda 表达式
1.1 语法举例
(String first, String second) -> first.length()-second.length()
(参数类型 参数名) ->{代码语句}.使用lambda表达式,实际就是创建该接口的实例对象
1.2 函数式接口
函数式接口用@FunctionalInterface注解,且接口内只有一个抽象方法
1.3 常见情况
情况 | 举例 |
---|---|
无参数,无返回值 | () -> System.out.println(); |
一个参数,无返回值 | (x) -> 操作 |
如果只有一个参数,小括号也可以省略 | x -> 操作 |
一个以上参数,且操作较复杂 | (x,y) -> {操作} |
一个以上参数,只有一条操作,有返回值,return,{}可以省略 | (x,y) -> Integer.compare(x,y) |
参数列表的数据类型可以不写,jvm会根据上下文进行推断 |
1.4 四大核心函数式接口
函数式接口名 | 抽象方法 | 方法说明 |
---|---|---|
Consumer |
void accept(T t) | 一个参数,无返回值类型 |
Supplier |
T get() | 无参数,指定返回值类型T |
Function<T, R>:函数型接口 | R apply(T t) | 一个参数,根据参数T类型返回R类型 |
Predicate |
boolean test(T t) | 判断T类型 |
1.5 举例
Consumer<String> consumer =s -> System.out.println(s); //使用lambda表达式就是创建该接口的实例对象,因此consumer为Consumer接口的实例对象,Consumer接口抽象方法accept规定传入一个参数,且无返回值,lambda表达式需要满足该规则
consumer.accept("hello, world!"); //调用accept方法,输出"hello,world!"
Supplier<String> supplier = ()-> s//使用lambda表达式就是创建该接口的实例对象,supplier是Supplier接口的实例对象,Consumer接口抽象方法get规定无参数,且返回指定类型,lambda表达式需要满足该规则
String s = supplier.get("hello, world!") //调用get,s值为"hello,world!"
使用总结
- lambda返回的就是接口的实例对象
- 根据参数个数(0,1,...),是否有返回值,返回值类型选择函数式接口,或自己写函数式接口
- 实现lambda表达式逻辑(符合参数个数要求,返回值类型即可,具体可以实现不同的逻辑)
2. 内部类
参考:
2.1 成员内部类
与成员变量类似.如果内部类持有外部类的引用,可能导致内部类没有执行完,外部类无法释放,有内存泄露风险.需要在外部类生命周期结束时候手动结束内部类生命周期.
public class Outer{
String s;
//成员内部类
class Inner{
}
}
2.2 局部内部类
定义在方法或作用域里的类,与局部变量类似,存在内存泄漏风险
public class Outter{
//成员内部类
class Inner{
String s;
}
public Innner getInner2(){
//局部内部类
class Inner2 extends Inner{
String s = "Inner2";
}
return new Inner2();
}
}
2.3 静态内部类
成员内部类前加static.静态内部类不会持有外部类的引用.不会造成内存泄漏
public class Outter{
String s;
static class Inner{
}
}
2.4 匿名内部类
只能使用一次,必须继承一个父类或实现一个接口,通俗理解为new一个接口
常用于多线程
public class Outter{
void test(){
new Thread(new Runnable(){
String s;
public void run(){}
}).start();
}
}
abstract class Person{
public abstract void eat();
}
public class Demo{
public static void main(String[] args){
Person p = new Person(){
//直接重写实现抽象方法
public void eat(){
System.out.println("eat something");
}
};
p.eat();
}
}
3. 异常
参考
3.1 层次与相关概念
概念 | 说明 |
---|---|
受查异常 | 在编译时被检测,必须在编译时进行处理,否则编译无法通过,通过try-catch或throws处理 |
非受查异常 | 不会再编译时被检测,通常为程序错误导致,Error,RuntimeException为非受查异常,其余为受查异常 |
Throwable | 所有异常类的基类 |
Error | Java程序运行时系统的内部错误,通常比较严重,如*Error,系统崩溃等 |
Exception | 狭义异常 |
运行时异常(仅针对Exception) | RuntimeException及其子类,如空指针,下标越界等,一般为程序逻辑错误导致,一般不用人为处理 |
非运行时异常(仅针对Exception) | RuntimeException以外的Exception子类.必须处理,如IO异常,SQL异常等 |
3.2 异常处理
-
在方法声明位置使用throws.抛给方法调用者,调用者处理异常
private static void readFile(String filepath) throws IOException{ //读取文件代码 }
-
方法体中throw手动抛出异
public static void main(String[] main){ try{ throw new Exception("异常"); }catch(Exception e){ System.out.println(e); } }
-
try-catch-finally语句
private static void readFIle(String filePath){ try{ //code }catch(FileNotFoundException | UnknownHostException e){ //处理异常 }catch(IOException e){ //处理异常 }finally{ //最终一定执行的部分 } }
注:
- catch异常有多个时,从上到下遵从异常有小到大的顺序
- 方法重写以后,不能比原方法抛出更多,更宽泛的异常,可以不抛,可以抛相同异常或异常子类
- catch中有return语句,finally依然会执行,如果finally中也有return语句,会覆盖前面的return语句(最好不要在finally中写return语句)
3.3 自定义异常
-
定义类继承Throwable或其子类
-
定义两个构造函数,一个无参,一个带有描述信息
public class MyException extends Exception{ public MyException(){} public MyException(String msg){ super(msg); } //... }
4. 泛型
理解:泛型就是把类型明确这一工作推迟到创建对象或调用方法的时候.类型化参数,即把类型当做参数进行传递.
好处:在编译时检查类型安全,并且所有强制类型转换都是自动,隐式的.
4.1 泛型类,接口,方法
- 常用泛型类:ArrayList,HashMap,HashSet
- 常用泛型接口:List,Map,Set
- 泛型方法:参数中需要多少泛型,返回值前面就要定义多少泛型
//泛型类
public class Test<T>{
}
//泛型接口
public interface Test<T>{
}
//泛型方法
public <T,K,V> void Test(T name, K value, V value){
}
4.2 通配符与类型参数
- ? : *通配符,不确定的java类型,通常用于泛型方法的调用和形参
- T : 具体的java类型,通常用于泛型类和方法的定义
- K V : 键值对
- E : element元素
- ? entends E : 上界通配符,表示参数化类型是E或其子类
- ? super E : 下界通配符,表示参数化类型是E或其父类