黑马程序员Java基础学习(二)

目录

继承

权限修饰符

继承的特点

方法重写

子类构造器的特点

子类构造器调用父类构造器的场景应用场景

补充知识:this(…)调用兄弟构造器

多态

多态下的类型转换问题

final

常量

设计模式

单例设计模式

枚举类

抽象类

抽象类的注意事项、特点

使用抽象类的好处

模板方法设计模式

接口

接口新增的三种方法

代码块

成员内部类

静态内部类

局部内部类

匿名内部类

匿名内部类在开发中的常见形式

函数式编程

Lambda表达式的省略规则

静态方法引用

实例方法引用

特定类的方法引用

构造器引用

常用API

String

String创建字符串对象的方式

String提供的常用方法

ArrayList

ArrayList集合

​编辑

GUI编程

Java的GUI编程包

常用的Swing组件

常见的布局管理器

布局管理器简介

什么是布局管理器?

常见的布局管理器

FlowLayout

BorderLayout

GridLayout

BoxLayout


继承

提高代码的重用性,减少一些重复代码的书写

继承就是Java中提供了一个关键字extends,用这个关键字,可以让一个类和另一个类建立起父子关系。

权限修饰符

继承的特点

1.单继承

Java是单继承模式:一个类只能继承一个直接父类

2.多层继承

Java不支持多继承,但支持多层继承

3.祖宗类

Java中所有的类都是object类的子类

4.就近原则

优先访问自己类中,自己类中的没有才会访问父类

继承后子类访问成员的特点:就近原则

1、在子类方法中访问其他成员(成员变量、成员方法),是依照就近原则的。
先子类局部范围找,然后子类成员范围找,然后父类成员范围找,如果父类范围还没有找到则报错。
2、如果子父类中,出现了重名的成员,会优先使用子类的,如果此时一定要在子类中使用父类的怎么办?
可以通过super关键字,指定访问父类的成员:

super.父类成员变量/父类成员方法

方法重写

当子类觉得父类中的某个方法不好用,或者无法满足自己的需求时,子类可以重写一个方法名称、参数列表一样的方法,去覆盖父类的这个方法,这就是方法重写。
重写小技巧:使用Override注解,他可以指定java编译器,检查我们方法重写的格式是否正确,代码可读性也会更好。

方法重写的其它注意事项
子类重写父类方法时,访问权限必须大于或者等于父类该方法的权限( public > protected > 缺省 )。
重写的方法返回值类型,必须与被重写方法的返回值类型一样,或者范围更小。
私有方法、静态方法不能被重写,如果重写会报错的。

子类构造器的特点

 子类的全部构造器,都会先调用父类的构造器,再执行自己。

子类构造器是如何实现调用父类构造器的:
默认情况下,子类全部构造器的第一行代码都是 super() (写不写都有) ,它会调用父类的无参数构造器。
如果父类没有无参数构造器,则我们必须在子类构造器的第一行手写super(….),指定去调用父类的有参数构造器。

子类构造器调用父类构造器的场景应用场景

super(…)调用父类有参数构造器的常见应用场景是什么?
 为对象中包含父类这部分的成员变量进行赋值。

补充知识:this(…)调用兄弟构造器

任意类的构造器中,是可以通过this(…) 去调用该类的其他构造器的。

this(...)和super(…)使用时的注意事项:
this(…) 、super(…) 都只能放在构造器的第一行,因此,有了this(…)就不能写super(…)了,反之亦然。

1、this(…)的作用是什么?
 在构造器中调用本类的其他构造器。
2、this(…)和super(…)的使用需要注意什么?
 都必须放在构造器的第一行。

多态

使用多态的好处
在多态形式下,右边对象是解耦合的,更便于扩展和维护。

定义方法时,使用父类类型的形参,可以接收一切子类对象,扩展性更强、更便利。
多态下会产生的一个问题,怎么解决?
多态下不能使用子类的独有功能。

解耦合;使用父类类型的变量作为方法的形参时,可以接收一切子类对象。

多态下的类型转换问题

1、类型转换有几种形式?能解决什么问题?
自动类型转换、强制类型转换。
可以把对象转换成其真正的类型,从而解决了多态下不能调用子类独有方法的问题。
2、强制类型转换需要注意什么?
存在继承/实现时,就可以进行强制类型转换,编译阶段不会报错。
但是,运行时,如果发现对象的真实类型与强转后的类型不同会报错(ClassCastException)。
3、强制类型转换前?Java建议我们做什么事情?
使用instanceof判断当前对象的真实类型:对象 instanceof 类型 。

综合案例—加油站支付小模块

某加油站为了吸引更多的车主,推出了如下活动,车主可以办理金卡和银卡。
卡片信息包括:车牌号码、车主姓名、电话号码、卡片余额。
金卡办理时入存金额必须>=5000元,银卡办理时预存金额必须>=2000元,金卡支付时享受8折优惠,银卡支付时享受9折优惠,金卡消费满200元可以提供打印免费洗车票的服务。
需求:请使用面向对象编程,完成该加油站支付机的存款和消费程序。

为了实现上述需求,我们可以定义几个类来代表卡片、车主信息以及支付逻辑。下面是一个简单的Java程序示例,它使用了面向对象的方法来建模这个加油站的支付系统。首先,我们需要创建一个Card接口,然后是GoldCardSilverCard两个具体类来实现这个接口。接着,我们还需要一个Owner类来存储车主的信息,并且有一个PaymentMachine类来处理存款和消费的操作。

// 卡片接口
interface Card {
    void recharge(double amount);
    boolean consume(double amount, boolean printTicket);
}

// 金卡类
class GoldCard implements Card {
    private String plateNumber;
    private double balance;
    
    public GoldCard(String plateNumber, double initialAmount) {
        if (initialAmount < 5000) {
            throw new IllegalArgumentException("Initial deposit for Gold Card must be at least 5000.");
        }
        this.plateNumber = plateNumber;
        this.balance = initialAmount;
    }

    @Override
    public void recharge(double amount) {
        balance += amount;
    }

    @Override
    public boolean consume(double amount, boolean printTicket) {
        double discountAmount = amount * 0.8; // 享受8折优惠
        if (balance >= discountAmount) {
            balance -= discountAmount;
            if (printTicket && discountAmount >= 200) {
                System.out.println("Providing a free car wash ticket.");
            }
            return true;
        } else {
            System.out.println("Insufficient balance.");
            return false;
        }
    }

    public double getBalance() {
        return balance;
    }
}

// 银卡类
class SilverCard implements Card {
    private String plateNumber;
    private double balance;

    public SilverCard(String plateNumber, double initialAmount) {
        if (initialAmount < 2000) {
            throw new IllegalArgumentException("Initial deposit for Silver Card must be at least 2000.");
        }
        this.plateNumber = plateNumber;
        this.balance = initialAmount;
    }

    @Override
    public void recharge(double amount) {
        balance += amount;
    }

    @Override
    public boolean consume(double amount, boolean printTicket) {
        double discountAmount = amount * 0.9; // 享受9折优惠
        if (balance >= discountAmount) {
            balance -= discountAmount;
            return true;
        } else {
            System.out.println("Insufficient balance.");
            return false;
        }
    }

    public double getBalance() {
        return balance;
    }
}

// 车主信息类
class Owner {
    private String name;
    private String phoneNumber;
    private Card card;

    public Owner(String name, String phoneNumber, Card card) {
        this.name = name;
        this.phoneNumber = phoneNumber;
        this.card = card;
    }

    public Card getCard() {
        return card;
    }
}

// 支付机类
class PaymentMachine {
    public static void main(String[] args) {
        // 创建银卡实例
        SilverCard silverCard = new SilverCard("京A12345", 2500);
        // 创建金卡实例
        GoldCard goldCard = new GoldCard("沪B67890", 5500);

        // 创建车主实例
        Owner owner1 = new Owner("张三", "13800138000", silverCard);
        Owner owner2 = new Owner("李四", "13900139000", goldCard);

        // 消费操作
        owner1.getCard().consume(200, false); // 使用银卡消费
        owner2.getCard().consume(250, true); // 使用金卡消费并打印洗车票

        // 输出余额
        System.out.println("Silver Card Balance: " + ((SilverCard)owner1.getCard()).getBalance());
        System.out.println("Gold Card Balance: " + ((GoldCard)owner2.getCard()).getBalance());
    }
}

final

final 关键字是最终的意思,可以修饰:类、方法、变量。
修饰类:该类被称为最终类,特点是不能被继承了。
修饰方法:该方法被称为最终方法,特点是不能被重写了。
修饰变量:该变量有且仅能被赋值一次。
final修饰变量的注意
final修饰基本类型的变量,变量存储的数据不能被改变。
final修饰引用类型的变量,变量存储的地址不能被改变,但地址所指向对象的内容是可以被改变的。

常量

设计模式

单例设计模式

什么是设计模式,设计模式主要学什么 ?  单例模式解决了什么问题 ?
具体问题的最优解决方案。
解决了什么问题? 怎么写?
确保某个类只能创建一个对象。

单例怎么写? 饿汉式单例的特点是什么?
把类的构造器私有;定义一个静态变量存储类的一个对象;提供一个静态方法返回对象。
在获取类的对象时,对象已经创建好了。

单例有啥应用场景,有啥好处?
任务管理器对象、获取运行时对象。
在这些业务场景下,使用单例模式,可以避免浪费内存。

懒汉单例模式的特点是什么?
要用类的对象时才创建对象(延迟加载对象)
懒汉单例模式怎么写?
把构造器私有。
定义一个类变量用于存储对象。
提供一个类方法,保证返回的是同一个对象。

枚举类

枚举类的特点

枚举类的常见应用场景

抽象类

抽象类的注意事项、特点

抽象类中不一定要有抽象方法,有抽象方法的类必须是抽象类。
类有的成员:成员变量、方法、构造器,抽象类都可以有。
抽象类最主要的特点:抽象类不能创建对象,仅作为一种特殊的父类,让子类继承并实现。
一个类继承抽象类,必须重写完抽象类的全部抽象方法,否则这个类也必须定义成抽象类。

使用抽象类的好处

模板方法设计模式

写法
1、定义一个抽象类。
2、在里面定义2个方法:
一个是模板方法:把共同的实现步骤放里面去。
一个是抽象方法:不确定的实现步骤,交给具体的子类来完成。

建议使用final关键字修饰模板方法,为什么?

模板方法是给子类直接使用的,不能被子类重写。
一旦子类重写了模板方法,模板方法就失效了。

总结:

1、模板方法设计模式解决了什么问题?
解决方法中存在重复代码的问题。
2、模板方法设计模式应该怎么写?
定义一个抽象类。
在里面定义2个方法,一个是模板方法:放相同的代码里,一个是抽象方法:具体实现交给子类完成。
3、模板方法建议使用什么关键字修饰?为什么
建议使用final关键字修饰模板方法。

接口

接口的好处

弥补了类单继承的不足,一个类同时可以实现多个接口,使类的角色更多,功能更强大。
让程序可以面向接口编程,这样程序员就可以灵活方便的切换各种业务实现(更利于程序的解耦合)。

接口新增的三种方法

1.默认方法(实例方法):使用default修饰,默认会被加上public修饰。

注意:只能使用接口的实现类对象调用

2.私有方法:必须用private修饰(JDK9开始支持)

3.类方法(静态方法):使用static修饰,默认会被加上public修饰。

注意:只能用接口名来调用

小结:

1、JDK8开始,接口中新增了哪些方法?
默认方法:使用default修饰,使用实现类的对象调用。
静态方法:static修饰,必须用当前接口名调用
私有方法:private修饰,jdk9开始才有的,只能在接口内部被调用。
他们都会默认被public修饰。
2、JDK8开始,接口中为啥要新增这些方法?
增强了接口的能力,更便于项目的扩展和维护。

接口的注意事项

1、接口与接口可以多继承:一个接口可以同时继承多个接口[重点]。
2、一个接口继承多个接口,如果多个接口中存在方法签名冲突,则此时不支持多继承,也不支持多实现。
4、一个类继承了父类,又同时实现了接口,如果父类中和接口中有同名的默认方法,实现类会优先用父类的。
5、一个类实现了多个接口,如果多个接口中存在同名的默认方法,可以不冲突,这个类重写该方法即可。

代码块

内部类

成员内部类

静态内部类

局部内部类

匿名内部类

匿名内部类在开发中的常见形式

案例—使用comparator接口的匿名内部类实现对数组进行排序

函数式编程

小结

1、什么是函数式编程?有是好处?
使用Lambda函数替代某些匿名内部类对象,从而让程序代码更简洁,可读性更好。
2、Lambda表达式是啥?有什么用?怎么写?
JDK8新增的一种语法,代表函数;可以用于替代并简化函数式接口的匿名内部类。
3、什么样的接口是函数式接口?怎么确保一个接口必须是函数式接口?
只有一个抽象方法的接口就是函数式接口。
在接口上加上@FuncationalInterface注解即可。    

案例—使用Lambda简化comparator接口的匿名内部类

Lambda表达式的省略规则

作用:用于进一步简化Lambda表达式的写法。
具体规则
参数类型全部可以省略不写。
如果只有一个参数,参数类型省略的同时“()”也可以省略,但多个参数不能省略“()”
如果Lambda表达式中只有一行代码,大括号可以不写,同时要省略分号“;”如果这行代码是return语句,也必须去掉return。

静态方法引用

类名::静态方法
使用场景
如果某个Lambda表达式里只是调用一个静态方法,并且“→”前后参数的形式一致,就可以使用静态方法引用。

实例方法引用

对象名::实例方法。
使用场景
如果某个Lambda表达式里只是通过对象名称调用一个实例方法,并且“→”前后参数的形式一致,就可以使用实例方法引用。

特定类的方法引用

特定类的名称::方法
使用场景
如果某个Lambda表达式里只是调用一个特定类型的实例方法,并且前面参数列表中的第一个参数是作为方法的主调,后面的所有参数都是作为该实例方法的入参的,则此时就可以使用特定类型的方法引用。

构造器引用

类名::new
使用场景
如果某个Lambda表达式里只是在创建对象,并且“→”前后参数情况一致,就可以使用构造器引用。

常用API

String

String代表字符串,它的对象可以封装字符串数据,并提供了很多方法完成对字符串的处理。

1、创建字符串对象,封装字符串数据

2、调用String提供的操作字符串数据的方法

String创建字符串对象的方式

String提供的常用方法

小结:

1. String是什么,可以做什么?
代表字符串,可以用来创建对象封装字符串数据,并对其进行处理。
2. String类创建对象封装字符串数据的方式有几种?
方式一: 直接使用双引号“...” 。
方式二:new String类,调用构造器初始化字符串对象。

ArrayList

集合是一种容器,用来装数据的,类似于数组。

1、创建ArrayList对象,代表一个集合容器

2、调用ArrayList提供的方法,对容器中的数据进行增删改查操作

ArrayList集合

1、集合是什么,有什么特点?
一种容器,用来存储数据的
集合的大小可变。
2、ArrayList是什么? 怎么使用?
是集合中最常用的一种,ArrayList是泛型类,可以约束存储的数据类型。
创建对象: 调用无参数构造器public ArrayList()初始化对象
调用增删改查数据的方法

GUI编程

 GUI,全称Graphical User Interface,是指图形用户界面。
 通过图形元素(如窗口、按钮、文本框等)与用户进行交互。
 与命令行界面(CLI)相比,GUI更加直观、友好。

为什么学习GUI编程?
增强用户体验
广泛应用于桌面应用程序开发
Java提供了强大的GUI编程支持

Java的GUI编程包

AWT(Abstract Window Toolkit)
提供了一组原生的GUI组件,依赖于操作系统的本地窗口系统
Swing
基于AWT,提供了更丰富的GUI组件,轻量级组件,不依赖于本地窗口系统

常用的Swing组件

JFrame: 窗口
JPanel:  用于组织其他组件的容器
JButton: 按钮组件
JTextField: 输入框
JTable: 表格
 

常见的布局管理器

布局管理器(Layout Manager)它们可以决定组件在容器中的布局方式,避免了手动设置每个组件的位置和大小,从而简化了GUI设计过程。

常见的布局管理器
FlowLayout
BorderLayout
GridLayout
BoxLayout

事件处理

GUI编程中,事件的处理是通过事件监听器(Event Listener)来完成的。

常用的时间监听器对象
 点击事件监听器 ActionListener
 按键事件监听器 KeyListener
 鼠标行为监听器 MouseListener
 

事件的几种常见的写法
第1种:直接提供实现类,用于创建事件监听对象
第2种:直接使用匿名内部类的对象,代表事件监听对象
第3种:自定义窗口,让窗口对象实现事件接口

布局管理器简介

什么是布局管理器?

布局管理器(Layout Manager)是Java Swing中用于控制容器中组件排列和大小的对象。它们决定了组件在容器中的布局方式,避免了手动设置每个组件的位置和大小,从而简化了GUI设计过程。

常见的布局管理器

FlowLayout
  • 简介: FlowLayout 是最简单的布局管理器,它按水平方向从左到右排列组件,当一行排满时,自动换到下一行。

  • 特点

    • 默认居中对齐,可以设置为左对齐或右对齐。

    • 适用于需要简单排列的场景。

  • 代码示例

import java.awt.*;

public class FlowLayoutExample {
    public static void main(String[] args) {
        JFrame frame = new JFrame("FlowLayout Example");
        frame.setSize(400, 300);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        frame.setLayout(new FlowLayout());

        frame.add(new JButton("Button 1"));
        frame.add(new JButton("Button 2"));
        frame.add(new JButton("Button 3"));
        frame.add(new JButton("Button 4"));
        frame.add(new JButton("Button 5"));

        frame.setVisible(true);
    }
}
BorderLayout
  • 简介: BorderLayout 将容器划分为五个区域:东、南、西、北和中(East, South, West, North, Center)。每个区域只能添加一个组件,未添加组件的区域保持空白。

  • 特点

    • 适用于需要在特定区域布局组件的场景。

    • 中间区域会占据所有剩余的空间。

  • 代码示例

import java.awt.*;

public class BorderLayoutExample {
    public static void main(String[] args) {
        JFrame frame = new JFrame("BorderLayout Example");
        frame.setSize(400, 300);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        frame.setLayout(new BorderLayout());

        frame.add(new JButton("North"), BorderLayout.NORTH);
        frame.add(new JButton("South"), BorderLayout.SOUTH);
        frame.add(new JButton("East"), BorderLayout.EAST);
        frame.add(new JButton("West"), BorderLayout.WEST);
        frame.add(new JButton("Center"), BorderLayout.CENTER);

        frame.setVisible(true);
    }
}
GridLayout
  • 简介: GridLayout 将容器划分为等大小的网格,每个网格中可以添加一个组件,所有组件大小相同。

  • 特点

    • 适用于需要均匀排列组件的场景。

    • 行和列的数量可以指定。

  • 代码示例

java复制代码import javax.swing.*;
import java.awt.*;

public class GridLayoutExample {
    public static void main(String[] args) {
        JFrame frame = new JFrame("GridLayout Example");
        frame.setSize(400, 300);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        frame.setLayout(new GridLayout(2, 3)); // 2行3列的网格

        frame.add(new JButton("Button 1"));
        frame.add(new JButton("Button 2"));
        frame.add(new JButton("Button 3"));
        frame.add(new JButton("Button 4"));
        frame.add(new JButton("Button 5"));
        frame.add(new JButton("Button 6"));

        frame.setVisible(true);
    }
}
BoxLayout
  • 简介: BoxLayout 能够沿着单一轴线(X轴或Y轴)排列组件。可以创建水平(X轴)或垂直(Y轴)排列的布局。

  • 特点

    • 适用于需要沿单一方向排列组件的场景。

    • 可以通过添加垂直或水平间隔(Glue、Strut)来调整组件间距。

  • 代码示例

import java.awt.*;

public class BoxLayoutExample {
    public static void main(String[] args) {
        JFrame frame = new JFrame("BoxLayout Example");
        frame.setSize(400, 300);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        JPanel panel = new JPanel();
        panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS)); // 垂直排列

        panel.add(new JButton("Button 1"));
        panel.add(Box.createVerticalStrut(10)); // 添加垂直间隔
        panel.add(new JButton("Button 2"));
        panel.add(Box.createVerticalStrut(10));
        panel.add(new JButton("Button 3"));
        panel.add(Box.createVerticalStrut(10));
        panel.add(new JButton("Button 4"));

        frame.add(panel);
        frame.setVisible(true);
    }
}

这些示例展示了布局管理器在Java Swing中的基本用法。你可以根据实际需求选择合适的布局管理器来设计你的GUI应用程序。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值