1.抽象类
1.抽象方法没有方法体,必须存在于抽象类,均使用abstract修饰
2.抽象类不能直接new对象,必须通过new子类的方式创建对象(多态向上转型)
3.子类必须重写抽象类中的所有抽象方法,除非子类也是抽象类
4.抽象类中可以书写普通属性,普通方法 静态方法 构造方法
5.抽象类作为父类,实现多态的方式与之前一致
public abstract class Animal {
// 属性
private String animalType;
public String getAnimalType() {
return animalType;
}
public void setAnimalType(String animalType) {
this.animalType = animalType;
}
public Animal(String animalType) {
this.animalType = animalType;
}
public Animal() {
}
public static void m1(){
System.out.println("Animal类中的m1方法 ");
}
// 方法
/**
* 1.抽象方法没有方法体 必须存在于抽象类 均使用abstract修饰
* 2.抽象类不能直接new对象 必须通过new子类的方式创建对象(多态向上转型)
* 3.子类必须重写抽象类中的所有抽象方法 除非子类也是抽象类
* 4.抽象类中可以书写普通属性 普通方法 静态方法 构造方法
* 5.抽象类作为父类 实现多态的方式与之前一致
*/
public abstract void eat();
}
2. 抽象类实现多态
public abstract class Door {
private String brand;
private double price;
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public abstract void open();
public abstract void close();
public Door(String brand, double price) {
this.brand = brand;
this.price = price;
}
public Door() {
}
}
3.final关键字
3.1 修饰属性
修饰属性:被final修饰的属性称之为常量 名称全部大写 多个单词之间使用下划线分割 常量只能被赋值一次
通常(99%)在定义的时候赋值 或者 在构造方法中赋值 这两种方式都是为了保证在使用常量之前是有值的
基本数据类型:值不能被改变
引用数据类型:地址不能被改变 地址中的内容(属性)是可以改变
public class TestFinalFiled {
final double PI = 3.14;
final int SEAT_COUNT;
final char [] SIGNS = new char[3];
public TestFinalFiled(){
SEAT_COUNT = 60;
}
public TestFinalFiled(double radius) {
SEAT_COUNT = 70;
this.radius = radius;
}
double radius;
public static void main(String[] args) {
TestFinalFiled testFinalFiled = new TestFinalFiled();
// testFinalFiled.pi = 3.24;
testFinalFiled.radius = 10;
System.out.println(testFinalFiled.radius * testFinalFiled.radius * testFinalFiled.PI);
// testFinalFiled.SIGNS = new char[2];
testFinalFiled.SIGNS[0] = 'a';
testFinalFiled.SIGNS[1] = 'b';
testFinalFiled.SIGNS[2] = 'c';
}
}
被final修饰的属性称之为常量 表示其值或者地址不能被改变
这样的数据通常也没有必要存在多份 所以实际开发中经常会用static final修饰不允许被改变的数据
因为只有一份 且 数据无法改变 所以通常也会再加上public修饰 称之为:全局 静态 常量
静态常量:通常在定义的时候赋值 或者 在静态代码块中赋值 这两种方式同样是为了保证在使用常量之前是有值的
public class TestStaticFinalField {
public static final double PI = 3.14;
static final String COUNTRY_NAME;
static{
COUNTRY_NAME = "中华人民共和国";
}
public TestStaticFinalField() {
}
}
3.2 修饰方法
final修饰的方法不能被子类重写
public class TestFinalMethod {
}
class A{
public final void m1(){
System.out.println("A类m1方法");
}
public void m2(){
System.out.println("A类m2方法");
}
}
class B extends A{
public void m2(){
}
}
3.3 修饰类
被final修饰的类不能被继承 String类就是使用final修饰的
public class TestFinalClass {
public static void main(String[] args) {
}
}
final class C{
}
class D {
}
4. 接口
1.接口中的方法默认都为全局抽象方法 即不管是否书写均使用public abstract修饰
2.接口不能直接new对象 必须通过new实现类(子类)的方式创建对象 (多态向上转型)
3.实现类(子类)必须实现(重写)接口中的所有抽象方法 除非实现类是抽象类 或者 是 接口
4.接口中不能书写普通属性、普通方法、构造方法、静态方法
5.一个类只能继承一个父类 一个实现类可以实现多个接口 接口也可以继承多个接口
6.接口实现多态的方式与之前一
面试题:Java支持多继承?
不支持 但是可以使用接口继承多个接口的方式 实现类似多继承的效果
public interface USB {
int A = 100; // 默认为全局静态常量 不管是否书写 均使用public static final修饰
/**
* 1.接口中的方法默认都为全局抽象方法 即不管是否书写均使用public abstract修饰
* 2.接口不能直接new对象 必须通过new实现类(子类)的方式创建对象 (多态向上转型)
* 3.实现类(子类)必须实现(重写)接口中的所有抽象方法 除非实现类是抽象类 或者 是 接口
* 4.接口中不能书写普通属性、普通方法、构造方法、静态方法
* 5.一个类只能继承一个父类 一个实现类可以实现多个接口 接口也可以继承多个接口
* 6.接口实现多态的方式与之前一致
*/
void connect();
}
public class Mouse implements USB {
@Override
public void connect() {
System.out.println("鼠标连接USB接口,可以操作电脑了");
}
}
5. 接口实现手机
接口是一种能力,实现一个接口,即表示具备一个能力,实现多个接口,即表示具备多个能力
关心实现类有何能力,而不关心实现细节
面向接口的约定而不考虑接口的具体实现
当前案例中,能不能将五个抽象方法全部书写在一个接口中呢?
不推荐,不可以,因为如果书写在一个接口中,将增加程序的耦合性,即任何一个手机子类实现了这个接口,将必须重写这个五个抽象方法,即拥有五个功能,将不能根据市场需求灵活的生产不同档次的手机产品。
public abstract class Phone {
private String brand;
private String type;
private double price;
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public Phone() {
}
public Phone(String brand, String type, double price) {
this.brand = brand;
this.type = type;
this.price = price;
}
public abstract void call();
public abstract void sendMessage(String message);
@Override
public String toString() {
return "Phone{" +
"brand='" + brand + '\'' +
", type='" + type + '\'' +
", price=" + price +
'}';
}
}
public class CommonPhone extends Phone implements NetWork,Audio,Game{
private String keyboardType;
public String getKeyboardType() {
return keyboardType;
}
public void setKeyboardType(String keyboardType) {
this.keyboardType = keyboardType;
}
public CommonPhone() {
}
public CommonPhone(String brand, String type, double price, String keyboardType) {
super(brand, type, price);
this.keyboardType = keyboardType;
}
@Override
public void call() {
System.out.println("普通手机打电话,按键拨号,体验还行");
}
@Override
public void sendMessage(String message) {
System.out.println("普通手机发短信,按键打字,体验一般:" + message);
}
@Override
public void playAudio(String audioName) {
System.out.println("普通手机播放音乐,音质感人:" + audioName);
}
@Override
public void playGame(String game) {
System.out.println("普通手机打游戏,体验一般:" + game);
}
@Override
public void connect() {
System.out.println("普通手机连接2G网络,体验很一般");
}
}
public class TestPhone {
public static void main(String[] args) {
SmartPhone huawei = new SmartPhone("华为", "mate 50 PRO MAX PLUS", 9.9, 25);
huawei.connect();
huawei.call();
huawei.sendMessage("睡了吗?");
huawei.playVideo("《小猪佩奇成人版》");
huawei.playAudio("《最炫民族风》");
huawei.playGame("《原神》");
huawei.takePhoto();
System.out.println("-------------------------------------------------------------------------------");
CommonPhone nokia = new CommonPhone("诺基亚", "N97", 8.8, "九键");
nokia.connect();
nokia.sendMessage("真的睡了吗?");
nokia.call();
nokia.playAudio("《发如雪》");
nokia.playGame("《贪吃蛇》");
}
}
6. 接口实现打印机
接口是一种约定,即表示一种规范
程序设计时面向接口的约定而不考虑具体实现
纸张是一种规范,接口也是一种规范,因为纸张和接口有我们公认的执行标准
public class Printer {
private InkBox inkBox;
private Paper paper;
public void setInkBox(InkBox inkBox){
this.inkBox = inkBox;
}
public InkBox getInkBox(){
return inkBox;
}
public void setPaper(Paper paper){
this.paper = paper;
}
public Paper getPaper(){
return paper;
}
public void print(){
System.out.println("使用" + this.getInkBox().getInkBoxType() + "墨盒在" + this.getPaper().getPaperSize() + "纸张上打印");
}
}
public interface InkBox {
/**
* 获取墨盒的具体类型
* @return
*/
String getInkBoxType();
}
public class BlackInkBox implements InkBox{
@Override
public String getInkBoxType() {
return "黑色";
}
}
public class ColorInkBox implements InkBox{
@Override
public String getInkBoxType() {
return "彩色";
}
}
public interface Paper {
/**
* 返回纸张具体的型号
* @return
*/
String getPaperSize();
}
public class A4 implements Paper{
@Override
public String getPaperSize() {
return "A4";
}
}
public class B5 implements Paper{
@Override
public String getPaperSize() {
return "B5";
}
}
public class Test {
public static void main(String[] args) {
Printer hp = new Printer();
Paper a4 = new A4();
Paper b5 = new B5();
InkBox black = new BlackInkBox();
InkBox color = new ColorInkBox();
hp.setPaper(a4);
hp.setInkBox(black);
hp.print();
}
}
7. 接口和抽象类
什么时候使用接口,什么时候使用抽象类呢?
推荐使用组合,即使用接口实现,因为类只能继承一个父类
当你关注事物的本质,使用抽象类
当你关注某个功能,使用接口