一、接口新特性
1.JDK8 接口特性
① 允许在接口中定义非抽象方法,但是需要使用关键字 default 修饰,这些方法就是默认方法
作用:解决接口升级的问题
接口中默认方法的定义格式:
格式:public default 返回值类型 方法名(参数列表) {}
范例:public default void show() {}
注意事项:
1. public可以省略, 但是default不能省略
2. 默认方法, 实现类是允许重写的, 但是需要去掉default关键字
3. 如果实现了多个接口, 多个接口中存在相同的默认方法, 实现类必须重写默认方法
interface Inter {
//调用时需要重写
void show();
void print();
//调用时不需要重新写,public省略
default void method(){
System.out.println("Inter...method");
}
}
class AInterImpl extends Object implements Inter {
@Override
public void show() {
System.out.println("AInterImpl...show");
}
@Override
public void print() {
System.out.println("AInterImpl...print");
}
//没有重写method()
}
public static void main(String[] args) {
AInterImpl a = new AInterImpl();
a.method();//主方法中可以直接进行调用
}
② 允许定义静态方法
既然接口已经允许方法带有方法体了, 干脆也放开静态方法, 可以类名调用
注意事项 :
1. public可以省略, 但是static不能省略
2. 接口中的静态方法, 只允许接口名进行调用, 不允许实现类通过对象调用
public static void main(String[] args) {
A.function();
}
interface A{
static void function(){
System.out.println("A...static...function");
}
}
2.JDK9 接口特性
接口中允许定义 private 私有方法
接口中静态方法的定义格式:
格式1:private 返回值类型 方法名(参数列表) {}
范例1:private void show() {}
格式2:private static 返回值类型 方法名(参数列表) {}
范例2:private static void method() {}
interface Inter {
public default void start(){
System.out.println("start方法执行...");
log();
}
public default void end(){
System.out.println("end方法执行...");
log();
}
public default void log() {
System.out.println("日志记录");
}
}
二、代码块(了解)
在Java类下,使用 { } 括起来的代码被称为代码块
1.局部代码块
位置:方法中定义
作用:限定变量的生命周期,及早释放,提高内存利用率
2.构造代码块
位置:类中方法外定义
特点:每次构造方法执行的时,都会执行该代码块中的代码,并且在构造方法执行前执
行
作用:将多个构造方法中相同的代码,抽取到构造代码块中,提高代码的复用性
3.静态代码块
位置:类中方法外定义
特点:需要通过static关键字修饰,随着类的加载而加载,并且只执行一次
作用:在类加载的时候做一些数据初始化的操作
class Student {
static String school;
static {
school = "学校";
System.out.println("static...Student类的静态代码块");
}
{
System.out.println("Student类的构造代码块");
System.out.println("好好学习");
}
public Student(){
{
System.out.println("局部代码块...");
}
System.out.println("空参构造方法...");
}
public Student(int num){
System.out.println("带参构造方法...");
}
}
三、内部类
内部类就是定义在一个类里面的类
class Outer {
// 内部类
class Inner { }
}
格式:外部类名.内部类名 对象名 = new 外部类对象().new 内部类对象();
范例:Outer.Inner in = new Outer().new Inner();
内部类中, 访问外部类成员 : 直接访问, 包括私有
外部类中, 访问内部类成员 : 需要创建对象访问
class Outer {
int num = 150;
class Inner {
int num = 110;
public void show(){
int num = 78;
System.out.println(num); // 78
System.out.println(this.num); // 110
System.out.println(Outer.this.num); // 150
}
}
}
1.成员内部类(了解)
2.静态内部类
有 static 修饰的成员内部类
class Outer { static class Inner { } }
格式:外部类名.内部类名 对象名 = new 外部类名.内部类对象();
范例:Outer.Inner in = new Outer.Inner();
3.局部内部类(了解)
局部内部类放在方法、代码块、构造器等执行体中。
4.匿名内部类(重要,掌握)
概述:匿名内部类本质上是一个特殊的局部内部类(定义在方法内部)
前提:需要存在一个接口或类
格式:new 类名 / 接口 () { }
new 类名(){} : 代表继承这个类
new 接口名(){} : 代表实现这个接口
匿名内部类可以使代码更加简洁,定义一个类的同时对其进行实例化
匿名内部类可以作为方法的实际参数进行传输
btn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("登录一下~~");
}
});
四、Lambda表达式
Lambda表达式是 JDK8 开始后的一种新语法形式。
作用:简化匿名内部类的代码写法。
简化格式:() -> {}
(匿名内部类被重写方法的形参列表) -> {
被重写方法的方法体代码。
}
注:-> 是语法形式,无实际含义
注意:Lambda 表达式只能简化函数式接口的匿名内部类的写法形式
(
函数式接口:
首先必须是接口、其次接口中有且仅有一个抽象方法的形式
通常我们会在接口上加上一个@FunctionalInterface注解,标记该接口必须是满足函数式
接口。
)
省略写法:
① 参数类型可以省略不写。
② 如果只有一个参数,参数类型可以省略,同时 () 也可以省略。
(如果没有参数,()不可以省略)
③ 如果Lambda表达式的方法体代码只有一行代码
可以省略大括号不写,同时要省略分号
此时,如果这行代码是return语句,必须省略return不写,同时也必须省略 ";" 不写
例:
public static void main(String[] args) {
useStringHandler(new StringHandler() {
@Override
public void printMessage(String msg) {
System.out.println("匿名内部类打印:" + msg);
}
});
System.out.println("---------------------");
//msg 前面省略了 String,->后面省略了{}
useStringHandler(msg -> System.out.println("Lambda打印:" + msg));
}
Lambda表达式和匿名内部类的区别:
使用限制不同
匿名内部类 : 可以操作类, 接口
Lambda表达式 : 只能操作函数式接口
实现原理不同
匿名内部类:编译之后,产生一个单独的.class字节码文件
Lambda表达式:编译之后,没有一个单独的.class字节码文件
五、窗体、组件、事件
1.窗体对象 JFrame(实际开发中用不到)
public class Test {
public static void main(String[] args) {
// 创建窗体对象
JFrame frame = new JFrame();
// 设置宽和高
frame.setSize(514, 595);
// 设置关闭模式 frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
// 设置窗体标题
frame.setTitle("窗体");
// 设置窗体可见
frame.setVisible(true);
}
}
窗体对象.getContentPane().add(组件);
setLayout(null); 取消默认布局
2.组件(实际开发中用不到)
① JButton
JButton() 创建一个没有设置文本或图标的按钮。
JButton(String text) 创建一个带文本的按钮。
② JLabel
用于展示文本和图片
JLabel(String text) 使用指定的文本创建一个 JLabel 对象
JLabel(Icon image) 创建一个具有指定图像的 JLabel 对象。
注意:如果多个组件摆放在同一个位置,后添加的组件,会被压在底部。
setBounds(50,50, 100,100);//设置组件位置x:50,y:50,width:100,height:100
3.事件
事件是可以被组件识别的操作
当你对组件干了某件操作之后,就会执行对应的代码
① ActionListener : 动作监听器 (鼠标点击, 空格按下)
事件源对象.addActionListener(
new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("我被点了!!!");
}
}
);
② KeyListener : 键盘监听器
事件源对象.addKeyListener(new KeyListener() {
@Override
public void keyTyped(KeyEvent e) { }
@Override
public void keyPressed(KeyEvent e) {
int keyCode = e.getKeyCode();
if(keyCode == 37) {
System.out.println("左移动业务代码");
}else if(keyCode == 38){
System.out.println("上移动业务代码");
}else if(keyCode == 39){
System.out.println("右移动业务代码");
}else if(keyCode == 40){
System.out.println("下移动业务代码");
}
}
@Override
public void keyReleased(KeyEvent e) { }
});
适配器设计模式:
设计模式(Design pattern)是一套被反复使用、多数人知晓的、经过分类编目
的、代码设计经验的总结。
使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性、程
序的重用性。
解决接口与接口实现类之间的矛盾问题
实现步骤
编写一个 xxxAdapter 类, 实现对应接口
重写内部所有抽象方法, 但方法都是空实现
让自己的类去继承适配器类, 重写自己需要的方法即可
为了避免其他类创建适配器类的对象, 使用 abstract 进行修饰
模板设计模式
把抽象类整体就可以看做成一个模板,模板中不能决定的东西定义成抽象方法
让使用模板的类(继承抽象类的类)
去重写抽象方法实现需求
模板设计模式的优势,模板已经定义了通用结构,使用者只需要关心自己需要实现
的功能即可
public abstract class CompositionTemplate {
public final void write() {
System.out.println("我的爸爸");
body();
System.out.println("啊~ 这就是我的爸爸~");
}
public abstract void body();
}
public class Tom extends CompositionTemplate {
@Override
public void body() {
System.out.println("我的爸爸回家...");
}
}