1、final
/* final修饰类与方法 当类声明为final时,该类为终极类(类的最终版本), 不能被子类所继承。 当方法声明为final时,该方法为终极方法(方法的最终 版本),不能被子类所重写。 final的应用: 1 某些方法(类)已经实现的很完善,不需要子类再去 扩展。 2 处于安全考虑,阻止子类去修改父类的实现。 当一个类声明为final时,类中所有的方法都隐式为final。 当方法是final时,由于该方法不能被子类重写, 在编译期间就可以决定调用哪一个方法,因此可以 提高一定的性能。 */ public class FinalTest { public static void main(String[] args) { } public void doSomething(Super s) { s.f(); } } class Super { public final void f() { } } class Sub extends Super { /*@Override public void f() { } */ } /* final class Super { } 错误,final类不能被子类继承。 class Sub extends Super { } */
2、抽象类与抽象方法
/* 抽象类与抽象方法 抽象类与抽象方法使用abstract修饰。 当类中某些功能(方法)不方便(或不知道)给出具体 实现,如果实现时,我们就可以将该类声明为抽象类。 而不方便(不知道)实现的方法声明为抽象方法。 抽象方法没有方法体。({}也没有) 抽象类是一个实现不完整的类,其设计的目的 就是为了让子类去继承的。抽象方法设计的目的 就是为了让子类去重写的(当父类的方法是抽象方法时, 也习惯说成子类实现父类的方法。)。 当类中含有抽象方法时,该类必须要声明为抽象类。 反之,当一个类声明为抽象类时,该类可以没有抽象 方法。 我们不能够创建抽象类的对象。(抽象类是实现不完整的类。) 但是,我们依然可以声明抽象类的引用,使其指向子类 的对象。 当子类继承了抽象的父类,子类就必须要实现抽象父类中 所有的抽象方法。否则,子类就需要也要声明为抽象类。 */ public class AbstractTest { public static void main(String[] args) { //错误,抽象类不能创建对象(实例化)。 //Shape s = new Shape(); //s.pe(); Shape s = new Rectangle(); } } abstract class Shape { //抽象方法 public abstract double pe(); public abstract double area(); } class Rectangle extends Shape { }
3、接口类型
/* 接口类型 接口只的是一种规范,该规范指出各个实现者 能够做到什么样的结果,而具体实现的细节,各个 实现者可以根据需要各自的需要灵活进行控制。 接口声明: interface 接口表示一种规范,该规范是通过接口中的抽象方法 来声明。该规范有类(class)来实现(implmenets)。 如果一个类实现了接口,则该类必须遵守接口中声明 的规范。即类需要实现接口中所有的抽象方法。否则, 该类必须声明为抽象类。 */ public interface School { //按时到校的规范 abstract void goToSchool(); } //小学生 class StudentA implements School { @Override public void goToSchool() { System.out.println("走路上学"); } } //幼儿园学生 class StudentB implements School { @Override public void goToSchool() { System.out.println("家长送上学"); } } //大学生 class StudentC implements School { @Override public void goToSchool() { System.out.println("逃学"); } }
4、接口的成员
/* 接口中的成员 接口中可以声明变量(常量),抽象方法, 默认方法,静态方法,内部类型(不考虑)。 1 接口中声明的成员变量一律是public, static,final类型的。 2 接口中声明的普通方法一律是public, abstract类型的。 3 即使1,2中的关键字不显式声明也是如此。 根据惯例,省略以上的关键字。 接口中所有的成员都是public类型的。无论我们 是否显式声明都是如此。 */ interface Member { //public static final int x = 1; int x = 1; //成员变量 //public abstract void f(); void f(); //抽象方法 //默认方法,具有具体的实现。(方法体) default void defF() { System.out.println("我是默认方法,具有实现"); } //静态方法,具有具体的实现。(方法体) static void staF() { System.out.println("我是静态方法,具有实现"); } }
5、接口的继承
/* 接口的继承 接口的继承与类的继承不同。在Java中,类只支持 单继承,即一个子类只能继承一个父类,而接口支持 多继承,即一个子接口可以同时继承多个父接口。 当子接口继承父接口,子接口会继承父接口中的成员。 子接口可以继承父接口中的成员变量,抽象方法, 默认方法,但是,不能继承父接口中的静态方法。 对于接口中声明的静态方法,直通通过声明该静态方法的 接口名进行访问。 */ interface SupInter1 { int x = 5; void f(); default void defF() { } static void staF() { } } interface SupInter2 { int y = 10; } interface SubInter extends SupInter1 { default void defF2() { System.out.println(x); f(); SupInter1.staF(); //错误,不能继承静态方法。 //staF(); //SubInter.staF(); } } //接口的多继承,使用“,”分隔。 interface SubInter2 extends SupInter1, SupInter2 { default void defF3() { System.out.println(x); System.out.println(y); } }
6、接口的实现
/* 接口的实现 接口设计的目的是为了让实现类去实现的。 类使用implements实现接口,一个类可以 实现多个接口,使用","进行分隔。 当一个类实现了某个接口,该类就会成为 接口的子类型(接口成为该类的父类型), 类可以继承接口中声明的成员。 类可以继承接口中声明的成员变量,抽象方法, 默认方法。但是,类不能继承接口中声明的静态方法。 因为接口中含有抽象的方法,所以,我们也不能创建 接口类型的对象。尽管如此,我们依然可以声明接口 类型的引用,令其指向实现类的对象。 通过父类型的引用,不能访问子类型新增的成员。 1 通过父类的引用,不能访问子类新增的成员。 2 通过接口的引用,不能访问实现类新增的成员。 */ interface InterA { int x = 1; void f(); default void defF() { } static void staF() { } } class ImplClass implements InterA { @Override public void f() { System.out.println("实现抽象方法。(实现规范细节)"); } public void g() { System.out.println(x); f(); defF(); //错误,类没有继承接口中的静态方法。 //staF(); //错误,不能创建接口类型的对象。 //InterA a = new InterA(); InterA a = new ImplClass(); a.f(); //错误 //a.g(); } }
7、求周长案例
interface Shape { //可以求周长 double pe(); //可以求面积 double area(); } class Rectangle implements Shape { private double width; private double height; public Rectangle(double width, double height) { this.width = width; this.height = height; } @Override public double pe() { return (width + height) * 2; } @Override public double area() { return width * height; } } class Triangle implements Shape { private double length; public Triangle(int length) { this.length = length; } @Override public double pe() { return length * 3; } @Override public double area() { double height = length * length - (length / 2) * (length / 2); height = Math.sqrt(height); return length * height / 2; } } class Circle implements Shape { private double radius; public Circle(double radius) { this.radius = radius; } @Override public double pe() { return 2 * Math.PI * radius; } @Override public double area() { return Math.PI * radius * radius; } } class Test { public void compute(Shape s) { System.out.println(s.pe()); System.out.println(s.area()); } public static void main(String[] args) { Test t = new Test(); t.compute(new Rectangle(10, 5)); t.compute(new Triangle(5)); t.compute(new Circle(5)); } }
8、子接口与默认方法
/* 子接口与默认方法 接口作为一种规范,一旦发布,就不能随意进行更改。 否则就会对各个实现者造成很大的影响。 怎样升级可以不对实现者造成影响: 1 使用子接口继承现有的接口,发布一个新的规范(对 原有规范的一个升级) 2 从JavaSE 8起,也可以选择第二种升级方法:增加 默认方法。 */ //1000 interface Car { void run(); //1002 //void fly(); default void fly() { System.out.println("默认方式的飞"); } } /* interface FlyCar extends Car { //新增的规范 void fly(); } */ //1001 class CarA implements Car { @Override public void run() { System.out.println("汽车跑动"); } /* @Override public void fly() { System.out.println("自己实现的飞的方式"); } */ } /* class CarA implements FlyCar { @Override public void run() { System.out.println("汽车跑动"); } @Override public void fly() { System.out.println("汽车飞"); } }
9、面向接口编程案例
现需要开发一个应用,模拟移动存储设备的读写,既计算机与 U盘、 MP3、移动硬盘等设备进行数据交换(读写操作)。 要实现U盘、 MP3、移动硬盘三种移动存储设备,要求计算机 能同这三种设备进行数据交换。 并且以后可能会有新的第三方的移动存储设备,所以计算机 必须有扩展性,能与目前未知而以后可能会出现的存储设备 进行数据交换。 各个存储设备间读、写的实现方法不同, U盘和移动硬盘只 有读,写这两个方法, MP3Player还有一个playMusic方法。
方案1:
public class Case1 { public static void main(String[] args) { Computer c = new Computer(); c.read(new FlashDisk()); c.read(new MP3Player()); c.read(new MobileHardDisk()); c.write(new FlashDisk()); c.write(new MP3Player()); c.write(new MobileHardDisk()); } } class FlashDisk { public void read() { System.out.println("U盘读"); } public void write() { System.out.println("U盘写"); } } class MP3Player { public void read() { System.out.println("MP3读"); } public void write() { System.out.println("MP3写"); } } class MobileHardDisk { public void read() { System.out.println("移动硬盘读"); } public void write() { System.out.println("移动硬盘写"); } } class Computer { public void read(FlashDisk f) { f.read(); } public void read(MP3Player mp3) { mp3.read(); } public void read(MobileHardDisk m) { m.read(); } public void write(FlashDisk f) { f.write(); } public void write(MP3Player mp3) { mp3.write(); } public void write(MobileHardDisk m) { m.write(); } }
方案2:
public class Case2 { public static void main(String[] args) { Computer c = new Computer(); c.setMs(new FlashDisk()); c.readData(); c.writeData(); c.setMs(new MP3Player()); c.readData(); c.writeData(); c.setMs(new MobileHardDisk()); c.readData(); c.writeData(); } } abstract class MobileStorage { public abstract void read(); public abstract void write(); } class FlashDisk extends MobileStorage { @Override public void read() { System.out.println("U盘读"); } @Override public void write() { System.out.println("U盘写"); } } class MP3Player extends MobileStorage { @Override public void read() { System.out.println("MP3读"); } @Override public void write() { System.out.println("MP3写"); } public void playMusic() { System.out.println("MP3所特有的功能,播放音乐!"); } } class MobileHardDisk extends MobileStorage { @Override public void read() { System.out.println("移动硬盘读"); } @Override public void write() { System.out.println("移动硬盘写"); } } class Computer { private MobileStorage ms; public void setMs(MobileStorage ms) { this.ms = ms; } public MobileStorage getMs() { return ms; } public void readData() { ms.read(); if (ms instanceof MP3Player) { MP3Player mp3 = (MP3Player) ms; mp3.playMusic(); } } public void writeData() { ms.write(); } }
方案3:
public class Case3 { public static void main(String[] args) { Computer c = new Computer(); c.setMs(new FlashDisk()); c.readData(); c.writeData(); c.setMs(new MP3Player()); c.readData(); c.writeData(); c.setMs(new MobileHardDisk()); c.readData(); c.writeData(); } } interface IMobileStorage { void read(); void write(); } class FlashDisk implements IMobileStorage { @Override public void read() { System.out.println("U盘读"); } @Override public void write() { System.out.println("U盘写"); } } class MP3Player implements IMobileStorage { @Override public void read() { System.out.println("MP3读"); } @Override public void write() { System.out.println("MP3写"); } } class MobileHardDisk implements IMobileStorage { @Override public void read() { System.out.println("移动硬盘读"); } @Override public void write() { System.out.println("移动硬盘写"); } } class Computer { private IMobileStorage ms; public void setMs(IMobileStorage ms) { this.ms = ms; } public IMobileStorage getMs() { return ms; } public void readData() { ms.read(); } public void writeData() { ms.write(); } }
方案4:
public class Case4 { public static void main(String[] args) { Computer c = new Computer(); c.setMs(new FlashDisk()); c.readData(); c.writeData(); c.setMs(new MP3Player()); c.readData(); c.writeData(); c.setMs(new MobileHardDisk()); c.readData(); c.writeData(); } } interface IReadable { void read(); } interface IWritable { void write(); } interface IMobileStorage extends IReadable, IWritable { } class FlashDisk implements IMobileStorage { @Override public void read() { System.out.println("U盘读"); } @Override public void write() { System.out.println("U盘写"); } } class MP3Player implements IMobileStorage { @Override public void read() { System.out.println("MP3读"); } @Override public void write() { System.out.println("MP3写"); } } class MobileHardDisk implements IMobileStorage { @Override public void read() { System.out.println("移动硬盘读"); } @Override public void write() { System.out.println("移动硬盘写"); } } class Computer { private IMobileStorage ms; public void setMs(IMobileStorage ms) { this.ms = ms; } public IMobileStorage getMs() { return ms; } public void readData() { ms.read(); } public void writeData() { ms.write(); } }