一阶段: JavaSE进阶学习04 --内部类及Lambad表达式
1.内部类
概念:在一个类中定义一个类。例:在一个类A的内部定义一个类B,类B就被称为内部类
//定义格式&举例
/*
格式:
class 外部类名{
修饰符 class 内部类名{
}
}
class Outer {
public class Inner {
}
}
内部类的访问特点
内部类可以直接访问外部类的成员,包括私有
外部类要访问内部类的成员,必须创建对象
/*
内部类访问特点:
内部类可以直接访问外部类的成员,包括私有
外部类要访问内部类的成员,必须创建对象
*/
/**
* @author 你的大龙猫啊
*/
public class Outer {
private int num = 10;
public class Inner {
public void show() {
System.out.println(num);
}
}
public void method() {
Inner i = new Inner();
i.show();
}
}
内部类按照在内中定义的位置分类:
1.成员内部类:
在类的成员位置
2.局部内部类:
(匿名内部类属于特殊的局部内部类):在类的局部位置(方法中)
2.成员内部类(理解)
1.成员内部类的定义位置
在类中方法,跟成员变量是一个位置
2.外界创建成员内部类格式
格式:外部类名.内部类名 对象名 = 外部类对象.内部类对象;
举例:Outer.Inner oi = new Outer().new Inner();
3.私有成员内部类
将一个类,设计为内部类的目的,大多数都是不想让外界去访问,所以内部类的定义应该私有化,私有化之后,再提供一个可以让外界调用的方法,方法内部创建内部类对象并调用
//示例
/**
* @author 你的大龙猫啊
*/
class Outer {
private int num = 10;
private class Inner {
public void show() {
System.out.println(num);
}
}
public void method() {
Inner i = new Inner();
i.show();
}
}
public class InnerDemo {
public static void main(String[] args) {
//Outer.Inner oi = new Outer().new Inner();
//oi.show();
Outer o = new Outer();
o.method();
}
}
4.静态成员内部类
1.静态成员内部类访问格式:外部类名.内部类名 对象名 = new 外部类名.内部类名();
2.静态成员内部类中的静态方法:外部类名.内部类名.方法名();
//示例
/**
* @author 你的大龙猫啊
*/
class Outer {
static class Inner {
public void show(){
System.out.println("inner..show");
}
public static void method(){
System.out.println("inner..method");
}
}
}
public class Test3Innerclass {
/*
静态成员内部类演示
*/
public static void main(String[] args) {
// 外部类名.内部类名 对象名 = new 外部类名.内部类名();
Outer.Inner oi = new Outer.Inner();
oi.show();
Outer.Inner.method();
}
}
3.局部内部类(理解)
1.局部内部类定义位置
局部内部类是在方法中定义的类
2.局部内部类方式方式
局部内部类,外界是无法直接使用,需要在方法内部创建对象并使用
该类可以直接访问外部类的成员,也可以访问方法内的局部变量
/**
* @author 你的大龙猫啊
*/
class Outer {
private int num = 10;
public void method() {
int num2 = 20;
class Inner {
public void show() {
System.out.println(num);
System.out.println(num2);
}
}
Inner i = new Inner();
i.show();
}
}
public class OuterDemo {
public static void main(String[] args) {
Outer o = new Outer();
o.method();
}
}
4.匿名内部类
-
匿名内部类的前提
存在一个类或者接口
,这里的类可以是具体类也可以是抽象类
-
匿名内部类的格式
-
格式:new 类名 ( ) { 重写方法 } new 接口名 ( ) { 重写方法 }
-
举例:
new Inter(){ @Override public void method(){} }
-
-
匿名内部类的本质
- 本质:是一个继承了该类或者实现了该接口的子类匿名对象
-
匿名内部类的细节
-
匿名内部类可以通过多态的形式接受
/** * @author 你的大龙猫啊 */ Inter i = new Inter(){ @Override public void method(){ } }
-
-
匿名内部类直接调用方法
/** * @author 你的大龙猫啊 */ interface Inter{ void method(); } class Test{ public static void main(String[] args){ new Inter(){ @Override public void method(){ System.out.println("我是匿名内部类"); } }.method(); // 直接调用方法 } }
匿名内部类在开发中的使用
当发现某个方法需要,接口或抽象类的子类对象,我们就可以传递一个匿名内部类过去,来简化传统的代码
概述:匿名内部类本质是一个特殊的局部内部类(定义在方法的内部)
前提:需要存在一个接口或类
5.Lambad表达式
Lambad表达式的使用前提:
1.使用Lambda必须要有接口
2.并且要求接口中有且仅有一个抽象方法
Lambad表达式的标准格式:
-
格式:
(形式参数) -> {代码块}
- 形式参数:如果有多个参数,参数之间用逗号隔开;如果没有参数,留空即可
- ->:由英文中画线和大于符号组成,固定写法。代表指向动作
- 代码块:是我们具体要做的事情,也就是以前我们写的方法体内容
-
组成Lambda表达式的三要素:
- 形式参数,箭头,代码块
(方法调用时的形式参数) ->{代码块(如输出语句等…)}
Lambda表达式的省略模式
省略规则:
1.参数类型可以省略,但是有多个参数的情况下,不能只省略一个
2.如果参数有且仅有一个,那么小括号可以省略
3.如果代码块的语句只有一个,可以省略大括号和分号,甚至是return
//省略模式演练
/**
* @author 你的大龙猫啊
*/
public interface Addable {
int add(int x, int y);
}
public interface Flyable {
void fly(String s);
}
public class LambdaDemo {
public static void main(String[] args) {
// useAddable((int x,int y) -> {
// return x + y;
// });
//参数的类型可以省略
useAddable((x, y) -> {
return x + y;
});
// useFlyable((String s) -> {
// System.out.println(s);
// });
//如果参数有且仅有一个,那么小括号可以省略
// useFlyable(s -> {
// System.out.println(s);
// });
//如果代码块的语句只有一条,可以省略大括号和分号
useFlyable(s -> System.out.println(s));
//如果代码块的语句只有一条,可以省略大括号和分号,如果有return,return也要省略掉
useAddable((x, y) -> x + y);
}
private static void useFlyable(Flyable f) {
f.fly("我要像宫崎骏里面的大龙猫一样,可以飞向天空");
}
private static void useAddable(Addable a) {
int sum = a.add(10, 20);
System.out.println(sum);
}
}
Lambada表达式和匿名内部类的区别:
-
所需类型不同
- 匿名内部类:可以是接口,也可以是抽象类,还可以是具体类
- Lambda表达式:只能是接口
-
使用限制不同
- 如果接口中有且仅有一个抽象方法,可以使用Lambda表达式,也可以使用匿名内部类
- 如果接口中多于一个抽象方法,只能使用匿名内部类,而不能使用Lambda表达式
-
实现原理不同
- 匿名内部类:编译之后,产生一个单独的.class字节码文件
- Lambda表达式:编译之后,没有一个单独的.class字节码文件。对应的字节码会在运行的时候动态生成
思考与分析:
分析以下需求,并用代码实现
interface Inter {
void show();
}
class Outer {
//补齐代码
}
public class OuterDemo {
public static void main(String[] args) {
Outer.method().show();
}
}
要求在控制台输出”HelloWorld”
/**
* @author 你的大龙猫啊
*/
/*
分析思路:从主方法入手 类名点方法 说明Outer里面的方法是静态的
然后发现是继续调用方法,说明调用方法之后会产生一个对象说明其有返回值
又发现show方法是在接口里面,不能直接创建对象,所以必须使用其实现类对象
此时解决的方案有三种:
1.使用匿名内部类(满足前提条件:有一个接口或类)
2.使用lambad表达式(满足前提条件:有一个接口,且接口里有且只有一个抽象方法)
3.写一个实现类实现接口 重写方法,调用方法并返回。
*/
class Outer {
//补齐代码
public static Inter method(){
//匿名内部类实现
/* return new Inter(){
@Override
public void show() {
System.out.println("HelloWorld");
}
};*/
//lambad表达式实现
return () -> System.out.println("HelloWorld");
}
}