内部类
1. 代码块
概述: 使用{}包裹起来的代码就是代码块
局部代码块
- 位置:定义在方法中
- 作用:限定变量的生命周期,让变量说占用的内存及早释放,提高内存的利用率
public class MethodCodeBlockDemo {
public static void main(String[] args) {
int a = 10;//如果不加代码块,此时变量a,是定义在方法当中,在整个main方法中都是有效的.
System.out.println(a);
//独立存在的大括号就是代码块.
{
int b = 10;
System.out.println(b);
}
//System.out.println(b);//报错了
}
}
构造代码块
- 位置:类中方法外
- 特点:每一次构造方法执行的时候都需要执行该代码块,并且优先于构造方法执行
- 作用:可以将多个构造方法中的公共代码抽出到构造代码块中,以提高代码的复用性
public class Student {
private String name;
private int age;
//1.位置:方法外,类里面.
//2.执行时机:优先于构造方法运行的.每一次创建对象的时候,都会先运行构造代码块,然后再执行构造方法
//3.作用:抽取构造方法中重复的代码.
{
System.out.println("开始执行构造方法了");
}
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
...
}
静态代码块
- 位置:类中方法外,并且需要用static进行修饰
- 特点:随着类的加载而执行,并且只执行一次
- 作用:进行系统的初始化的工作
代码块的执行顺序:先执行静态代码块,构造代码块,构造方法
2. 内部类
2.1概述及特点
- 概述:就是把某一个类定义到另一个类里面
- 特点:
- 内部类可以直接访问外部类的成员,包含私有的
- 外部类想要访问内部类的成员,就必须创建对象
public class Outer1 {
String OuterName;
private int OuterAge;
public void OuterMethod(){
//外部类要访问内部类的成员,直接访问是报错的,需要创建内部类的对象
//System.out.println(InnerName);
//System.out.println(InnerAge);
Inner1 inner1 = new Inner1();
System.out.println(inner1.InnerName);
inner1.InnerMethod();
}
// 内部类
public class Inner1{
String InnerName;
private int InnerAge;
public void InnerMethod(){
System.out.println(OuterName);
System.out.println(OuterAge);
}
}
public static void main(String[] args) {
Outer1 outer1 = new Outer1() ;
outer1.OuterMethod();
}
}
2.2成员内部类
内部类按照定义的位置不同,可以分为两种:
- 成员内部类:把这个内部类定义在外部类的成员位置
- 局部内部类:把这个内部类定义在方法中
成员内部类常见的修饰符
- public
- 其他类创建内部类的对象格式:外部类名.内部类名 对象名 = new 外部类对象.内部类对象;
Outer.Inner oi = new Outer().new Inner();
- private
- 其他类不能直接访问,只能在外部类中创建该类对象进行访问
- static
- 其他类创建内部对象的格式:外部类名.内部类名 对象名 = new 外部类名.内部类名();
Outer.Inner oi = new Outer.Inner();
2.3 局部内部类
局部内部类:把这个内部类定义在方法中
特点:
- 其他类无法直接访问局部内部类,局部内部类只能定义在该类的方法中进行访问
- 局部内部类是可以访问外部类的成员的,也可以访问方法中的局部变量
public class Outer3 {
String OuterName;
// 定义了一个方法outerMethod
public void outerMethod(){
// 局部变量
int number = 10;
// 局部内部类
class Inner3{
public void innerMethod(){
System.out.println(OuterName);
System.out.println(number);
System.out.println("局部内部类的方法运行了");
}
}
// 创建Inner3这个局部内部类的对象
Inner3 inner3 = new Inner3();
inner3.innerMethod();
}
}
2.4 匿名内部类
匿名内部类:是一种特殊的内部类
前提:必须先定义一个类或者接口
new 类名/接口名() {
// 重写方法
};
// 接口
public interface Inter {
public abstract void show() ;
}
new Inter() { // 本质上是一个实现了Inter这个接口的子类对象
public void show() {
System.out.println("Inter...show......") ;
}
};
// 类
public class Student {
public void show() {
System.out.println("Student...show......") ;
}
}
new Student() { // 本质上是一个继承了Student这个类的子类对象
public void show() {
System.out.println("Student...show......") ;
}
};
本质:实现某一接口或者继承某一类的子类
使用场景:把匿名内部类作为方法参数进行传递
public class AnonymityClassDemo {
public static void main(String[] args) {
//匿名内部类
new Inter(){
@Override
public void show() {
System.out.println("匿名内部类");
}
};
//需求:调用goSwimming方法
//创建实现类的对象
//SwimmingImpl swimming = new SwimmingImpl();
//调用方法
//goSwimming(swimming);
new Swimming() {
@Override
public void swim() {
System.out.println("匿名内部类方式----去游泳了");
}
}.swim();
System.out.println("------------------------------");
// 多态
Swimming swimming = new Swimming() {
@Override
public void swim() {
System.out.println("匿名内部类方式----去游泳了");
}
};
swimming.swim();
System.out.println("------------------------------");
//就可以用匿名内部类去改进
goSwimming(
new Swimming() {
@Override
public void swim() {
System.out.println("匿名内部类方式----去游泳了");
}
}
);
}
public static void goSwimming(Swimming swimming){
swimming.swim();
}
}
3. lambda表达式
3.1 lambda
lambda表达式是jdk1.8以后提供的新的语法规则
lambda表达式体现的是另一种编程思想:函数式编程
函数:在数学中函数表示有输入量,输出量的一种计算方案,强调的是做什么.
java语言是面向对象的语言,面向对象的语言关注的是对象,谁可以帮我做什么事情
- 面向对象的编程思想的代码体现
goSwimming(
new Swimming() {
@Override
public void swim() {
System.out.println("匿名内部类方式----去游泳了");
}
}
);
- 函数式编程思想的代码体现
//lambda表达式方式
goSwimming(()->{
System.out.println("lambda方式---去游泳了");
});
3.2 格式
(参数类型 参数名称) -> { 方法体代码 }
使用lambda表达式的前提:必须有一个接口,并且这个接口中只有一个抽象方法(函数式接口)
3.4 省略格式
lambda表达式在使用的时候,也存在省略格式.
- 参数类型 可以省略,但是有多个参数的时候,不能只省略一个
- 如果参数有且只有一个时,可以省略小括号
- 如果 方法体代码只有一条,可以省略大括号和分号,甚至是return
3.5 注意事项
- 使用lambda表达式必须有接口,并且要求接口中除了Object类的方法抽象表示形式以外,有且仅有一个抽象方法
- 必须有上下文环境,才能推导出lambda对应接口
lambda表达式和匿名内部类的区别
- 使用前提
- 匿名内部类:可以是接口,也可以是抽象类,还可以是具体的类
- lambda表达式:只能是接口,接口中有且仅有一个抽象方法
- 运行原理
- 匿名内部类:编译后,产生一个独立的.class文件
- lambda表达式:编译后,没有单独的.class文件,对应的字节码文件会在运行时动态生成