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();
}
}