JavaSE进阶-day04
一、 内部类
1.内部类-成员内部类【了解】(视频01) (7‘’)
-
内部类概述
在一个类中定义一个类。举例:在一个类A的内部定义一个类B,类B就被称为内部类
public class Outer { //Inner 被称为内部类 public class Inner { } }
-
成员内部类的创建格式
外部类名.内部类名 对象名 = new 外部类对象().new 内部类对象();
例子:Outer.Inner i = new Outer().new Inner();
public class Test1Inner { public static void main(String[] args) { /* 创建内部类对象的格式: 外部类名.内部类名 对象名 = new 外部类对象().new 内部类对象(); */ Outer.Inner i = new Outer().new Inner(); System.out.println(i.num); i.show(); } } class Outer { class Inner { int num = 10; public void show(){ System.out.println("Inner..show"); } } }
-
内部类的访问特点
内部类访问外部类:内部类可以直接访问外部类的成员,包括私有
class Outer { private int a = 10; private void method(){ System.out.println("Outer..method"); } class Inner { int num = 10; public void show(){ System.out.println("Inner..show"); // 内部类, 访问外部类成员, 可以直接访问, 包括私有 System.out.println(a); method(); } } }
外部类访问内部类: 外部类要访问内部类的成员,必须创建对象
class Outer { class Inner { int num = 10; } public void method2(){ //外部类 使用 内部类,正常创建对象即可 Inner inner = new Inner(); System.out.println(inner.num); } }
-
内部类的定义位置
成员内部类: 在类的成员位置定义
局部内部类: 在类的局部位置定义。 如:方法中定义的类
自由练习-8分钟(成员内部类的创建格式)
2.私有成员内部类-静态内部类【了解】(视频02) (7‘’)
-
private
私有成员内部类访问:只能在自己所在的外部类中创建对象访问。
public class Test2Innerclass { /* 私有成员内部类演示 */ public static void main(String[] args) { Outer o = new Outer(); o.method(); } } class Outer { private class Inner { public void show(){ System.out.println("inner..show"); } } public void method(){ Inner i = new Inner(); i.show(); } }
-
static
静态成员内部类访问格式:外部类名.内部类名 对象名 = new 外部类名.内部类名();
静态成员内部类中的静态方法:外部类名.内部类名.方法名();
public class Test3Innerclass { /* 静态成员内部类演示 */ public static void main(String[] args) { // 外部类名.内部类名 对象名 = new 外部类名.内部类名(); Outer.Inner oi = new Outer.Inner(); oi.show(); //静态成员内部类中的静态方法 Outer.Inner.method(); } } class Outer { static class Inner { public void show(){ System.out.println("inner..show"); } public static void method(){ System.out.println("inner..method"); } } }
自由练习-8分钟
3.局部内部类【了解】(视频03) (4‘’)
局部内部类,外界是无法直接使用,需要在方法内部创建对象并使用
该类可以直接访问外部类的成员,也可以访问方法内的局部变量
public class Test4Innerclass {
/*
局部内部类:
编写位置: 方法中
访问方式: 只能在方法中, 创建对象并访问
*/
public static void main(String[] args) {
Outer o = new Outer();
o.method();
}
}
class Outer {
private int a = 10;
public void method(){
int b = 20;
class Inner {
public void show(){
System.out.println("show...");
//可以直接访问外部类的成员,也可以访问方法内的局部变量
System.out.println(a);
System.out.println(b);
}
}
Inner i = new Inner();
i.show();
}
}
小结【了解】
内部类 | 说明 | 如果获取对象 |
---|---|---|
成员内部类 | 普通的成员内部类(定义在成员位置) | Outer.Inner i = new Outer().new Inner(); |
静态内部类 | 使用static修饰的成员内部类 | Outer.Inner oi = new Outer.Inner(); |
私有内部类 | 使用private修饰的成员内部类 | Inner i = new Inner(); (注意:只能在本类中获取对象 ) |
局部内部类 | 定义在方法中 | Inner i = new Inner(); (注意:只能在本方法中获取对象) |
4.匿名内部类【重点】(视频04) (12‘’)
概述:匿名内部类本质上是一个特殊的局部内部类(定义在方法内部)
前提:存在一个类或者接口,这里的类可以是具体类也可以是抽象类
public class Test5Innerclass {
/*
匿名内部类:
是一个继承了该类或者实现了该接口的子类匿名对象
前提: 需要存在类\接口
格式:
new 类名 \ 接口名 (){
重写方法
}
*/
public static void main(String[] args) {
// 匿名内部类的理解: 将继承\实现, 方法重写, 创建对象, 放在了一步进行.
// 解释: 实现了Inter接口的, 一个实现类对象.
new Inter() {
@Override
public void show() {
System.out.println("我是匿名内部类中的show方法");
}
}.show();
}
}
interface Inter {
void show();
}
多态的形式接收、匿名内部类对象
public class Test5Innerclass {
public static void main(String[] args) {
// 情况: 接口中存在多个方法,可以使用多态的形式接收,匿名内部类的实现对象
Inter2 i = new Inter2() {
@Override
public void show1() {
System.out.println("show1...");
}
@Override
public void show2() {
System.out.println("show2...");
}
};
i.show1();
i.show2();
}
}
interface Inter2 {
void show1();
void show2();
}
5.匿名内部类的使用场景【重点】(视频05) (4‘’)
使用场景:匿名内部类可以直接做为参数传递给其他方法
public class TestSwimming {
public static void main(String[] args) {
goSwimming(new Swimming() {
@Override
public void swim() {
System.out.println("铁汁, 我们去游泳吧");
}
});
}
/**
* 使用接口的方法
*/
public static void goSwimming(Swimming swimming){
swimming.swim();
}
}
/*
游泳接口
*/
interface Swimming {
void swim();
}
自由练习-8分钟
二、Lambda表达式
1.Lambda初体验和函数式编程思想【】(视频06) (7‘’)
-
Lambda初体验
public class TestSwimming { public static void main(String[] args) { goSwimming(() -> {System.out.println("铁汁, 我们去游泳吧");}); } /** * 使用接口的方法 */ public static void goSwimming(Swimming swimming) { swimming.swim(); } } /* 游泳接口 */ interface Swimming { void swim(); }
-
函数式编程思想
面向对象编程思想强调”通过对象的形式做事情”
函数式编程思想强调”做什么,而不是以什么形式去做
2.Lambda表达式的格式说明和前提条件【应用】(视频07) (8‘’)
-
Lambda表达式的格式
-
组成Lambda表达式的三要素: 形式参数,箭头,代码块
-
格式:(形式参数) -> {代码块}
形式参数:如果有多个参数,参数之间用逗号隔开;如果没有参数,留空即可
->:由英文中画线和大于符号组成,固定写法。代表指向动作
代码块:是我们具体要做的事情,也就是以前我们写的方法体内容
-
-
Lambda表达式的前提条件
- 一个接口
- 接口中有且仅有一个抽象方法
-
Lambda练习-无参数无返回值
public class TestLambda { /* Lambda表达式的使用前提 1. 一个接口 2. 接口中有且仅有一个抽象方法 练习1: 1. 编写一个接口(ShowHandler) 2. 在该接口中存在一个抽象方法(show),该方法是无参数无返回值 3. 在测试类(ShowHandlerDemo)中存在一个方法(useShowHandler) 方法的的参数是ShowHandler类型的 在方法内部调用了ShowHandler的show方法 */ public static void main(String[] args) { useShowHandler(new ShowHandler() { @Override public void show() { System.out.println("我是匿名内部类中的show方法"); } }); // Lambda实现 useShowHandler(() -> {System.out.println("我是Lambda中的show方法")}); } public static void useShowHandler(ShowHandler showHandler){ showHandler.show(); } } interface ShowHandler { void show(); }
3.Lambda练习-带参数无返回值【应用】(视频08) (5‘’)
public class StringHandlerDemo {
/*
1.首先存在一个接口(StringHandler)
2.在该接口中存在一个抽象方法(printMessage),该方法是有参数无返回值
3.在测试类(StringHandlerDemo)中存在一个方法(useStringHandler)
方法的的参数是StringHandler类型的
在方法内部调用了StringHandler的printMessage方法
*/
public static void main(String[] args) {
useStringHandler(new StringHandler() {
@Override
public void printMessage(String msg) {
System.out.println("我是匿名内部类" + msg);
}
});
// Lambda实现
useStringHandler((msg) -> {
System.out.println("我是Lambda表达式" + msg);
});
}
public static void useStringHandler(StringHandler stringHandler) {
stringHandler.printMessage("itheima");
}
}
interface StringHandler {
void printMessage(String msg);
}
自由练习-8分钟
4.Lambda练习-无参数有返回值【应用】(视频09) (5‘’)
public class RandomNumHandlerDemo {
/*
1. 首先存在一个接口(RandomNumHandler)
2. 在该接口中存在一个抽象方法(getNumber),该方法是无参数但是有返回值
3. 在测试类(RandomNumHandlerDemo)中存在一个方法(useRandomNumHandler)
方法的的参数是RandomNumHandler类型的
在方法内部调用了RandomNumHandler的getNumber方法
*/
public static void main(String[] args) {
useRandomNumHandler(new RandomNumHandler() {
@Override
public int getNumber() {
Random r = new Random();
int num = r.nextInt(10) + 1;
return num;
}
});
useRandomNumHandler( () -> {
Random r = new Random();
int num = r.nextInt(10) + 1;
return num;
// 注意: 如果lambda所操作的接口中的方法, 有返回值, 一定要通过return语句, 将结果返回
// 否则会出现编译错误
} );
}
public static void useRandomNumHandler(RandomNumHandler randomNumHandler){
int result = randomNumHandler.getNumber();
System.out.println(result);
}
}
interface RandomNumHandler {
int getNumber();
}
自由练习-8分钟
5.Lambda练习-带参数带返回值【应用】(视频10) (4‘’)
public class CalculatorDemo {
/*
1. 首先存在一个接口(Calculator)
2. 在该接口中存在一个抽象方法(calc),该方法是有参数也有返回值
3. 在测试类(CalculatorDemo)中存在一个方法(useCalculator)
方法的的参数是Calculator类型的
在方法内部调用了Calculator的calc方法
*/
public static void main(String[] args) {
useCalculator(new Calculator() {
@Override
public int calc(int a, int b) {
return a + b;
}
});
useCalculator((int a, int b)->{
return a + b;
});
}
public static void useCalculator(Calculator calculator) {
int result = calculator.calc(10, 20);
System.out.println(result);
}
}
interface Calculator {
int calc(int a, int b);
}
自由练习-8分钟
6.Lambda省略模式【了解】(视频11) (7‘’)
省略规则
参数类型可以省略。但是有多个参数的情况下,不能只省略一个
如果参数有且仅有一个,那么小括号可以省略
如果代码块的语句只有一条,可以省略大括号,分号,return
public class Test6 {
public static void main(String[] args) {
/*useInter( (double a, double b) -> {
return a + b;
});*/
//参数类型可以省略。但是有多个参数的情况下,不能只省略一个
//如果代码块的语句只有一条,可以省略大括号,分号,return
useInter((a, b) ->a + b);
}
public static void useInter(Inter i) {
double result = i.method(12.3, 22.3);
System.out.println(result);
}
}
interface Inter {
// 用于计算 a + b 的结果并返回
double method(double a, double b);
}
public class StringHandlerDemo {
public static void main(String[] args) {
useStringHandler(new StringHandler() {
@Override
public void printMessage(String msg) {
System.out.println("我是匿名内部类" + msg);
}
});
// Lambda实现 - 如果参数有且仅有一个,那么小括号可以省略
useStringHandler(msg -> System.out.println("我是Lambda表达式" + msg));
}
public static void useStringHandler(StringHandler stringHandler) {
stringHandler.printMessage("itheima");
}
}
interface StringHandler {
void printMessage(String msg);
}
自由练习-8分钟
三、匿名内部类和Lambda表达式的区别
1.匿名内部类和Lambda表达式的区别【了解】(视频12) (5‘’)
-
所需类型不同
匿名内部类:可以是接口,也可以是抽象类,还可以是具体类
Lambda表达式:只能是接口
-
使用限制不同
如果接口中有且仅有一个抽象方法,可以使用Lambda表达式,也可以使用匿名内部类
如果接口中多于一个抽象方法,只能使用匿名内部类,而不能使用Lambda表达式
-
实现原理不同
匿名内部类:编译之后,产生一个单独的.class字节码文件
Lambda表达式:编译之后,没有一个单独的.class字节码文件。对应的字节码会在运行的时候动态生成