Day2:语法——接口
什么是包:
-
包是用来分门别类的管理各种不同类的, 类似于文件夹、建包利于程序的管理和维护。
-
建包的语法格式: package 公司域名倒写· 技术名称。报名建议全部英文小写, 且具备意义
package com.itheima.javabean;
public class Student {
}
-
建包语句必须在第一行, 一般丨DEA 工具会帮助创建
导包:
-
相同包下的类可以直接访问, 不同包下的类必须导包, 才可以使用! 导包格式: import 包名.类名;
-
加入一个类中需要用到不同类,而这个两个类的名称是一样的,那么默认只能导入一个类,另一个类要带包名访问。
什么是权限修饰符:
权限修饰符: 是用来控制一个成员能够被访问的范围。
可以修饰成员变量, 方法, 构造器, 内部类, 不同权限修饰符修饰的成员能够被访问的范围将受到限制。
权限修饰符的分类和具体作用范围:
权限修饰符: 有四种作用范围由小到大( private 一> 缺省一> protected 一> public )
| 修饰符 |
同一个类中 |
同一个包中其他类 |
不同包下的子类 |
不同包下的无关类 |
| private |
√ |
|
|
|
| 缺省 |
√ |
√ |
|
|
| protected |
√ |
√ |
√ |
|
| public |
√ |
√ |
√ |
√ |
final的作用:
final 关键字是最终的意思, 可以修饰( 类、方法、变量)
修饰类: 表明该类是最终类, 不能被继承。
修饰方法: 表明该方法是最终方法, 不能被重写。
修饰变量:表示该变量第一次赋值后, 不能再次被赋值( 有且仅能被赋值一次) 。
final修饰变量的注意事项:
-
final修饰的变量是基本类型: 那么变量存储的数据值不能发生改变
-
final修饰的变量是引用类型: 那么变量存储的地址值不能发生改变, 但是地址指向的对象内容是可以发生变化的。
常量
-
常量是使用了public static final 修饰的成员变量,必须有初始化值,而且执行的过程中其值不能被改变。
-
常量的作用和好处: 可以用于做系统的配置信息, 方便程序的维护, 同时也能提高可读性。
public class Constant {
public static final String SCHOOL_NAME = "传智教育";
public static final String LOGIN NAME = "admin";
public static final String PASS WORD = "123456";
常量命名规范: 英文单词全部大写,
多个单词下划线连接起来。
常量的执行原理
-
在编译阶段会进行“ 宏替换" , 把使用常量的地方全部替换成真实的字面量。就是把SCHOOL_NAME 转换为 "传智教育";
-
这样做的好处是让使用常量的程序的执行性能与直接使用字面量是一样的。
选择常量做信息标志和分类:
枚举的概述:
枚举是Java中的一种特殊类型;
作用:为了做信息的标志和信息的分类
定义枚举类的格式:
修饰符 enum 枚举名称{
第一行都是罗列枚举类实例的名称
}
public enum Season {
//枚举的第一行必须罗列枚举类的对象名称,建议全部大写
SPRING,SUMMER,AUTUMN,WINTER;
}
反编译后的特征:
/*反编译后的结果 利用cmd命令javac 文件名字 javap反编译
public final class Season extends java.lang.Enum<Season>{
public static final Season SPRING;
public static final Season SUMMER;
public static final Season AUTUMN;
public static final Season WINTER;
public static Season[] values();
public static Season valueOf(java.lang.String);
static {};
}
*/
枚举的特征:
-
枚举类都是继承了枚举类型: java.lang.Enum
-
枚举都是最终类, 不可以被继承。
-
构造器的构造器都是私有的, 枚举对外不能创建对象。
-
枚举类的第一行默认都是罗列枚举对象的名称的。
-
枚举类相当于是多例模式。
常量和枚举做信息标志和分类的区别:
-
虽然常量可以实现可读性,但是入参值不受约束,代码相对不够严谨;
-
枚举的话可读性好,入参约束严谨,代码优雅,是最好的信息分类技术
btn1.addActionListener(new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
move(Oriebtation.up);
}
});
btn2.addActionListener(new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
move(Oriebtation.down);
}
});
btn3.addActionListener(new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
move(Oriebtation.left);
}
});
btn4.addActionListener(new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
move(Oriebtation.right);
}
});
public static void move(Oriebtation o){
switch (0){
case up:
System.out.println("向上跑");
break;
case down:
System.out.println("向下钻");
break;
case left:
System.out.println("向左跑");
break;
case right:
System.out.println("向右跑");
break;
}
}
public enum Oriebtation {
up,down,left,right;
}
抽象类:
-
在Java 中abstract 是抽象的意思, 可以修饰类、成员方法。
-
abstract 修饰类, 这个类就是抽象类; 修饰方法, 这个方法就是抽象方法。
修饰符 abstract class 类名{
修饰符abstract 返回值类型方法名称( 形参列表);
}
public abstract class Animal{
public abstract void run();
}
注意事项
-
抽象方法只有方法签名,不能声明方法体
-
一个类中如果定义了抽象方法,这个类必须声明成抽象类,否则报错
抽象类的使用场景
-
抽象类可以理解成不完整的设计图, 一般作为父类, 让子类来继承。
-
当父类知道子类一定要完成某些行为, 但是每个子类该行为的实现又不同, 于是该父类就把该行为定义成抽象方法的形式,具体实现交给子类去完成。此时这个类就可以声明成抽象类。
-
一个类如果继承了抽象类,那么这个类必须重写完抽象类的全部抽象方法,否则这个类也必须定义成抽象类
public abstract class Animal{
public abstract void run();
}
抽象类特征和注意事项:
-
类有的成员( 成员变量、方法、构造器) 抽象类都具备
-
抽象类中不一定有抽象方法, 有抽象方法的类一定是抽象类
-
一个类继承了抽象类必须重写完抽象类的全部抽象方法, 否则这个类也必须定义成抽象类。
-
不能用abstract 修饰变量、代码块、构造器。
-
最重要的特征: 得到了抽象方法, 失去了创建对象的能力( 有得有失)
final和abstract的关系
-
互斥关系
-
abstract 定义的抽象类作为模板让子类继承,final 定义的类不能被继承。
-
抽象方法定义通用功能让子类重写/ fina 啶义的方法子类不能重写。
-
因为final修饰的类不能被继承,abstract修饰的类必须要继承,不然没有意义
抽象类的应用型知识:模板方法模式
使用场景:当系统中出现同一个功能多处在开发,而该功能大部分代码是一样的,只有其中部分可能不同的时候
模板方法模式实现步骤:
-
把功能定义成一个所谓的模板方法,放在抽象类中,模板方法中只定义通用且能确定的代码;
-
模板方法中不能决定的功能定义成抽线方法让具体子类去实现。
-
模板方法建议用final修饰,会更专业,由于模板方法是直接给子类使用的,不是让子类重写的,一旦子类重写了模板方法,则模板方法失效
public abstract class Student {
/**
* 正式:声明了模板方法模式
*/
public final void write(){
System.out.println("\t\t\t\t\t<my father>");
System.out.println("你的爸爸是什么样的,说说:");
/*
正文部分,每个子类都要写,每个子类写的情况不一样
因此,模板方法把正文不能分定义成抽象方法,交给
具体的子类来完成
*/
System.out.println(writeMain());
System.out.println("我的爸爸太好了");
}
public abstract String writeMain();
}
模板方法模式解决的问题:
-
提高了代码的复用性
-
模板方法已经定义了通用结构, 模板方法不能确定的部分定义成抽象方法, 交给子类实现因此, 使用者只需要关心自己需要实现的功能即可。
接口
接口 的定义和特点:
接口的格式:用关键字interface来定义
public interface 接口名{
//常量
//抽象方法
}
接口的用法:
-
接口就是用来被类实现的(implements)的,实现接口的类称为实现类。实现类可以理解成所谓的子类
修饰符 class 实现类 implements 接口1,接口2,接口3,...{
}
实现的关键字:implements
-
从上面可以看出,接口可以被类单实现,也可以被类多实现
接口实现的注意事项:
-
一个类实现接口,必须重写完全部接口的全部抽象方法,否则这个类需要定义成抽象类。
基本小结:
-
类和类的关系:单继承
-
类和接口的关系:多实现
-
接口和接口的关系:多继承,一个接口可以同时继承多个接口
public class BasketBallMan implements SportMan{
@Override
public void rule() {
}
@Override
public void eat() {
}
@Override
public void run() {
}
@Override
public void competition() {
}
}
public interface SportMan extends Law,People{//law和people都是接口
void run();
void competition();
}
接口多继承的作用:
接口新增方法,注意事项
第一种:默认方法
-
类似之前写的普通实例方法:必须用default修饰
-
默认会public修饰,需要用接口的实现类对象来调用
default void run(){
System.out.println("---开始跑---")
}
第二种:静态方法
默认会public修饰,必须static修饰。
注意:接口的静态方法必须用本身的接口名来调用
public interface SportManInter {
/**
* 从jdk8开始,默认方法(实例方法)
* 必须default修饰,默认用public修饰
* 默认方法,接口不能创建对象,这个方法只能过继给实现类,由实现类对象调用
*/
default void fun() {
System.out.println("happy!happy!");
//public default void fun(){
go();
}
/**
* 2.静态方法
* 必须使用static修饰,默认用public修饰
* 接口的静态方法,必须接口名自己调用
*/
static void Inaddr() {
System.out.println("每天进步一点点");
}
/**
* 3.私有方法
* jdk1.9才开始支持的
* 必须在接口内部才能被访问
*/
private void go(){
System.out.println("--工作就是生活--");
}
}
class Sportman implements SportManInter {
}
class Test {
public static void main(String[] args) {
Sportman s = new Sportman();
s.fun();
SportManInter.Inaddr();
}
}
static void inAddr(){
System.out.println("我们都是黑马")
}
第三种:私有方法
就是私有的实例方法,必须使用private修饰
只能在本类中被其他的默认方法或私有方法访问
private void go(){
System.out.println("--准备--")
}
JDK8以后新增了哪些方法:
-
默认方法:default修饰,实现类对象调用
-
静态方法:static修饰,必须用当前接口名调用
-
私有方法:private修饰,JDK9开始才有的,只能在接口内部被调用
-
他们都会默认被public修饰
接口的注意事项:
1 、接口不能创建对象->接口是更加彻底的抽象
2 、一个类实现多个接口, 多个接口中有同样的静态方法不冲突。
3 、一个类继承了父类, 同时又实现了接口, 父类中和接口中有同名方法, 默认用父类的。
4 、一个类实现了多个接口, 多个接口中存在同名的默认方法, 不冲突, 这个类重写该方法即可。
5 、一个接口继承多个接口, 是没有问题的, 如果多个接口中存在规范冲突则不能多继承。