赞
踩
有句很扎心的话,我对这世间唯一的不满就是这世间总是让更懂事的人承受的更多。
生活中,往往你越善解人意,就越没人在乎你的委屈,时间,让你学会了坚强,经历,让你学会了
成长,年龄,让你学会了迁就。
你不计较,你不动怒,你让步,你宽容,人生中充满了各种破事,你说最多的就是没事,然而有些人,却习惯了
这样的你,一次次的得寸进尺,丝毫不在乎你的感受,正如此生未完成所说:三角恋里每一次都是哪个主动波汗,
苦苦纠缠,步步相逼获胜,哪怕你有那么一点点心软,不忍看着,他左右为难,腹背受敌,那么兵败的终归是你。
有些人轻轻挥手就什么都有,而有些人拼尽了全力,却还是一无所有,会哭的孩子,有糖吃,不会哭的孩子,只能冷暖自知,其实你
不必那么懂事。一定要学会摆脱他人的期待,不再习惯取悦他人,找到真正的自己。
一路走来,跨过荆棘,是为了遇见春暖花开,而不是为了,去将就一个或是凑合一段生活,别人最
懂事的人受最多的委屈。
—————— 一禅心灵庙语
随着继承层次中一个个新子类的定义,类变得越来越具体,而父类则更一般,更通用。类的设计应该保证父类和子类能够共享特征,有时将一个父类设计得非常抽象,以至于它没有具体的实例,这样的类叫做抽象类。
用 abstract
关键字来修饰一个类,这个类叫做抽象类。
abstract
可以用来修饰 类,方法 。
abstract class Person{
}
new
。虽然我们的抽象类是不能 new ,但是却是必须要构造器(构造方法的)。因为抽象类是用来 继承 使用的,而继承就涉及到了 子类实例化的全过程 :子类继承父类(抽象类)则就必须调用父类中的构造器,所以我们的抽象类是必须要有构造器的。这一点需要注意的。
我们为父类(抽象类)附加上 空参的构造器 就可以了,让子类实例化对象,有父类的无参构造器调用
被abstract
修饰的方法叫做 “抽象方法”。
abstract class Person{
// 抽象方法
abstract public void show();
}
抽象方法:没有方法体,只有方法的声明。
普通的类中是不能定义抽象方法的,抽象类中才可以定义抽象方法。所以就有了这么一句话:包含抽象方法的类,一定是抽象类(注意是类,除了接口) ,反之抽象类不一定就 有抽象方法。 因为抽象类中也可以没有抽象方法。
abstract
修饰类或者该子类也定义为抽象类
abstract
修饰符的注意事项:
抽象类体现的就是一种模板模式 的设计,抽象类作为多个子类的通用模板,子类在抽象类的基础上进行扩展,改造,但子类总体上会保留抽象类的行为方式。
解决问题的思路:
当功能内部一部分实现是确定的,一部分实现是不确定的。这时可以把不确定的部分暴露出去,让子类去实现,换句话说,在软件开发中实现一个算法时,整体步骤很固定,通用,这些步骤已经在父类中写好了。但是某些部分易变,易变部分可以抽象出来,供不同子类实现。这就是一种 模板模式 。
举例具体代码如下:
public class TemplateTest { public static void main(String[] args) { Bank b1 = new DrawMoneys(); b1.process(); // 多态:动态绑定;调用子类重写的方法transactBusiness() System.out.println("**********************"); Bank b2 = new ManageMoneys(); // 多态 b2.process(); // 多态调用的是子类重写的方法transactBusiness() } } abstract class Bank{ public void drawNumber(){ System.out.println("取号排队"); } // 抽象方法: 不确定处理怎样的业务需求:让子类继承实现 abstract public void transactBusiness(); public void end(){ System.out.println("最后:业务评价"); } // 重点 // final 无法被重写,最后将所有操作整合在一起处理, public final void process() { this.drawNumber(); // 取号 // 重点,实际调用的是: 子类重写的方法,多态 this.transactBusiness(); // 对应的业务处理,执行子类中重写的抽象方法 this.end(); // 最后业务评价 } } // 取钱,操作 class DrawMoneys extends Bank{ @Override // 重写继承的抽象类的抽象方法(无法确定的部分) public void transactBusiness(){ System.out.println("业务处理:取钱"); } } // 存钱操作。 class ManageMoneys extends Bank{ @Override // 重写所继承的抽象类的抽象方法(无法确定的部分) public void transactBusiness() { System.out.println("业务处理: 存钱"); } }
一方面,有时必须从几个类中派生出一个子类,继承它们所有的属性和方法。但是,Java不支持多重继承。有了接口,就可以得到多重继承的效果。
另一方面,有时必须从几个类中抽取出一些共同的行为特征,而它们之间又没有is-a的关系,仅仅是具有相同的行为特征而已。例如:鼠标、键盘、打印机、扫描仪、摄像头、充电器、MP3机、手机、数码相机、移动硬盘等都支持USB连接。
接口就是规范,定义的是一组规则,体现了现实世界中“如果你是/要…则必须能…”的思想。继承是一个"是不是"的关系,而接口实现则是"能不能"的关系。
接口的本质是契约,标准,规范,就像我们的法律一样。制定好后大家都要遵守。
接口使用 interface
关键字定义修饰类
interface Flyable{
}
Java中,接口 和 类 是并列的两个结构。
接口是一种特殊的抽象类,这种抽象类中只包含常量和抽象方法的定义(JDK7.0及之前),而没有变量和方法的实现。
接口中的所有成员变量都默认是由 public static final
修饰的,对于编译器而言一般都是会省略的不写的。因为是被 final 修饰的所以是无法修改其中的变量的值的。被称为常量。
package blogs.blog3; public class InterfaceTest { public static void main(String[] args) { System.out.println(Flyable.MAX_SPEED); // 可以直接通过类名.的方式直接访问,省略的是 public static final; System.out.println(Flyable.Min_SPEED); } } interface Flyable{ public static final int MAX_SPEED = 7900; int Min_SPEED = 1; // 默认省略了 public static final }
public abstract
修饰的,不过一般是会被省略不写的,但是默认是会附加上的interface Flyable{ public static final int MAX_SPEED = 7900; int Min_SPEED = 1; // 默认省略了 public static final // 抽象方法 public abstract void fly(); // 省略了 public abstract void stop(); } class Plane implements Flyable { @Override public void fly() { } @Override public void stop() { } }
implements
, 接口与接口之间的关系是 继承关系。implements
的方式来使用: 如果对应实现类,必须重写接口中所有的抽象方法(abstract) 默认省略的,不然编译报错;如果没有重写接口中的抽象方法,则将该类也定义为 接口 interface 才行。
implements
实现关系
interface AA{ // 抽象方法 public abstract void funAA(); } interface BB{ // 抽象方法 public abstract void funBB(); } // 一个类实现多个接口 class CC implements AA,BB{ @Override public void funAA() { } @Override public void funBB() { } }
interface AA{ // 抽象方法 public abstract void funAA(); } interface BB{ // 抽象方法 public abstract void funBB(); } // 接口与接口之间是: 多继承关系 interface DD extends AA,BB{ }
Java 8中,你可以为接口添加静态方法和默认方法。从技术角度来说,这是完全合法的,只是它看起来违反了接口作为一个抽象定义的理念。
接口中的静态方法:
使用 static
关键字修饰,可以通过 “接口名.方法名” 的方式直接调用静态方法(因为是静态方法),并执行其方法体我们经常在相互一起使用的类中使用静态方发,你可以在标准库中找到像Collection/Collections或者 Path/Paths这样成对的接口和类。
interface CompareA{
// 接口中定义:静态方法
public static void method1(){
System.out.println("接口中的静态方法 method1");
}
}
package blogs.blog3; public class InterfaceJDK8 { public static void main(String[] args) { // 调用接口中静态方法: 直接接口名.方法 CompareA.method1(); } } interface CompareA{ // 接口中定义:静态方法 public static void method1(){ System.out.println("接口中的静态方法 method1"); } }
接口中的静态方法,不可以被重写,只能被接口自己是使用,通过,“接口名.方法名”调用。因为不是抽象方法,所以对于实现类来说是不需要重写的,也无法重写。
package blogs.blog3; public class InterfaceJDK8 { public static void main(String[] args) { // 调用接口中静态方法 CompareA.method1(); SubClass subClass = new SubClass(); subClass.method1(); // jdk8中接口中定义的静态方法无法 实例对象调用,只能接口名.方法名的方式调用 } } interface CompareA{ // 接口中定义:静态方法 public static void method1(){ System.out.println("接口中的静态方法 method1"); } } class SubClass implements CompareA{ }
接口中的默认方法:
使用 default
关键字修饰,可以通过实现类对象来调用,我们在已有的接口中提供,新方法的同时保持了与旧版本代码的兼容性,比如:Java 8 API 中对 Collection, List, Comparator 等接口提供了丰富的默认方法。
接口中的默认方法的调用:通过实例化 new 实现类的对象。再通过对象的方式调用其中的默认的方法.
同样因为接口不是抽象方法,所以没有一定要重写的要求。
interface CompareA{
// 接口中定义: 默认方法
default void method2(){
System.out.println("接口中的默认方法");
}
}
package blogs.blog3; public class InterfaceJDK8 { public static void main(String[] args) { SubClass subClass = new SubClass(); subClass.method2(); // 调用接口中的默认方法 } } interface CompareA{ // 接口中定义: 默认方法 default void method2(){ System.out.println("接口中的默认方法"); } // 接口中定义:静态方法 public static void method1(){ System.out.println("接口中的静态方法 method1"); } } class SubClass implements CompareA{ }
接口中的默认方法:是可以重写的,重写默认方法和多态性中的动态绑定是一样的。实现运行的是调用重写以后的方法。
package blogs.blog3; public class InterfaceJDK8 { public static void main(String[] args) { SubClass subClass = new SubClass(); subClass.method2(); // 调用接口中的默认方法 } } interface CompareA{ // 接口中定义: 默认方法 default void method2(){ System.out.println("接口中的默认方法"); } // 接口中定义:静态方法 public static void method1(){ System.out.println("接口中的静态方法 method1"); } } class SubClass implements CompareA{ // 重写接口中的默认方法 @Override public void method2(){ System.out.println("实现类重写的默认方法"); } }
如果接口中和继承的父类中含有同名同参数的方法,而实现类又没有重写其中 同名同参数的方法的情况下,默认调用的是继承类中类父类中的方法,不是接口中的方法——> 类优先,如果重写了就是子类中的方法先调用
寻找的属性和方法的顺序是: 1.本类,2.父类,3.接口
package blogs.blog3; public class InterfaceJDK8 { public static void main(String[] args) { SubClass subClass = new SubClass(); subClass.method2(); // 调用接口中的默认方法 } } interface CompareA{ // 接口中定义: 默认方法 default void method2(){ System.out.println("接口中的默认方法:同名同参数的方法"); } // 接口中定义:静态方法 public static void method1(){ System.out.println("接口中的静态方法 method1"); } } class SuperClass{ public void method2(){ System.out.println("SuperClass 父类中的 同名同参数的方法"); } } class SubClass extends SuperClass implements CompareA{ // 重写接口中的默认方法 @Override public void method2(){ System.out.println("实现类重写的默认方法,本类中的:同名同参数的方法"); } }
在这里插入图片描述
注释掉:本类中重写的方法:重新运行看看。
如果实现类实现了多个接口,而这多个接口又定义同名同参数的默认方法:那么在实现类上,如果没有重写此(同名同参数同方法名)的情况下,是会报错的。:接口冲突。注意这是在 同名同参数同方法的接口中的 默认方法 才会,抽象方法是不会的。
解决方式:本实现类中重写其中的默认方法。
interface CompareA{ // 接口中定义: 默认方法 default void method2(){ System.out.println("CompareA接口中的: 默认方法"); } // 接口中定义:静态方法 public static void method1(){ System.out.println("接口中的静态方法 method1"); } } interface CompareB{ // JDK8 接口: 默认方法 default void method2() { System.out.println("CompareB: 接口中的默认方法"); } } class SubClass implements CompareA,CompareB{ }
解决方式:重写其中默认方法
interface CompareA{ // 接口中定义: 默认方法 default void method2(){ System.out.println("CompareA接口中的: 默认方法"); } // 接口中定义:静态方法 public static void method1(){ System.out.println("接口中的静态方法 method1"); } } interface CompareB{ // JDK8 接口: 默认方法 default void method2() { System.out.println("CompareB: 接口中的默认方法"); } } class SubClass implements CompareA,CompareB{ @Override public void method2() { System.out.println("实例类中重写的默认方法"); } }
代理模式是Java开发中使用较多的一种设计模式。代理设计就是为其他对象提供一种代理以控制对这个对象的访问。
应该场景:
比如你要开发一个大文档查看软件,大文档中由大的图片,有可能一个图片有 100MB,在打开文件时,不可能将所有的图片都显示出来,这样就可以使用代理模式,当需要查看图片时,用 proxy
来进行大图片的打开。
静态代理(静态定义代理类)
动态代理(动态生成代理类)
JDK自带的动态代理,需要反射等知识
具体实现代码如下:
package day16; // 代理模式 public class StaticProxyTest { public static void main(String[] args) { Star s = new Proxy(new RealStar()); s.confer(); s.signContract(); s.bookTicket(); s.sing(); s.collectMoney(); } } interface Star { void confer();// 面谈 void signContract();// 签合同 void bookTicket();// 订票 void sing();// 唱歌 void collectMoney();// 收钱 } class RealStar implements Star { public void confer() { } public void signContract() { } public void bookTicket() { } public void sing() { System.out.println("明星:歌唱~~~"); } public void collectMoney() { } } class Proxy implements Star { private Star real; public Proxy(Star real) { this.real = real; } public void confer() { System.out.println("经纪人面谈"); } public void signContract() { System.out.println("经纪人签合同"); } public void bookTicket() { System.out.println("经纪人订票"); } public void sing() { // 调用的是: 对应 Star 多态重写的方法 real.sing(); } public void collectMoney() { System.out.println("经纪人收钱"); } }
如下代码是否存在编译错误:
package blogs.blog3; public class InterviewTest { public static void main(String[] args) { new C().px(); } } interface A{ int x = 0; } class B{ int x = 1; } class C extends B implements A{ public void px(){ System.out.println(x); } }
解析:
System.out.println(x); 其中的 x 变量是不明确的,因为该变量名 x ,对于 C 类来说,其中的父类 B 也有,其中的实现接口 A 其中也有 x,对于这两个 父类,接口中的同名变量,存在歧义,其中的编译器无法识别其要调用的是,哪个变量。所以报错。
解决方法:明确其中调用的是那边的变量即可,如下
package blogs.blog3; public class InterviewTest { public static void main(String[] args) { new C().px(); } } interface A{ int x = 0; } class B{ int x = 1; } class C extends B implements A{ public void px(){ System.out.println(super.x); // 调用父类中的变量 x System.out.println(A.x); // 调用接口中的变量 x ,因为接口中的变量默认是被public static final修饰的 } }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
观察如下代码:是否存在错误
package blogs.blog3; public class InterviewTest { } interface Playable{ public abstract void play(); } interface Bounceable{ public abstract void play(); } interface Rollable extends Playable,Bounceable { Ball ball = new Ball("Pingpang"); } class Ball implements Rollable { private String name; public Ball(String name) { this.name = name; } public String getName() { return name; } @Override public void play() { ball = new Ball("Football"); } }
解析:
ball = new Ball(“Football”); 报错原因是: 因为对应的接口 Rollable 中已经定义了 Ball ball = new Ball(“Pingpang”); 全局变量,对于
接口中的属性,默认是被 public static final 修饰的,其中被 final 修饰的变量是无法被修改的,而这里你想要重新修改赋值的变量是 ball 同名的无法修改。
一个类继承了 类 ,实现了接口 , 重写了 func() 方法,父类,接口,本类中都有 func() 方法,如何调用执行其中对应父类,接口中的 func()方法
public class InterviewTest { public static void main(String[] args) { Students students = new Students(); students.play(); } public static void main2(String[] args) { new C().px(); } } interface People{ // 接口中的默认方法 default void func() { System.out.println("People 接口中的默认方法 func()"); } // 接口中的静态方法 public static void method(){ System.out.println("People接口中的静态方法"); } } class Persons{ public void func(){ System.out.println("父类 Persons中的 func()方法"); } } class Students extends Persons implements People{ @Override public void func() { System.out.println("本类中重写的 func()方法"); } public void play(){ this.func(); // 调用执行本类中的 func()重写的方法 super.func(); // 调用执行父类中的 func()方法 People.super.func(); // 调用接口中的默认方法 func() People.method(); // 调用接口中的静态方法 method(); } }
abstract
可以用来修饰 类,方法
抽象类不可以 实例化 new 对象,但必须要有构造器(构造方法) 用于继承中的子类的实例化全过程调用父类中的构造器。
abstract 不能修饰 属性,代码块,构造器,因为无法重写
abstract 不能修饰: private 修饰的方法,final修饰的方法,final 修饰的类,静态方法,都是无法重写的。
抽象类中的抽象方法必须被所 extends
继承的类全部重写,不然编译无法通过。
接口中的抽象方法必须被 implements
实现类全部重写,不然编译无法通过
接口 JDK7 之前的接口:只包含常量和方法的定义
implements
实现关系,接口与接口之间是 :extends 继承关系接口 JDK8 之后的接口:
default
关键字修饰,可以通过实现类对象来调用 ”实例对象.方法名“,默认方法可以被重写。接口的主要用途就是被实现类实现。(面向接口编程)
接口的本质是契约,标准,规范,就像我们的法律一样。制定好后大家都要遵守。
定义类的语法格式是:先写 extends ,后写 implements
class SubClass extends SuperClass implements InterfaceA{ }
限于自身水平,其中存在的错误,希望大家给予指教,韩信点兵——多多益善,谢谢大家,后会有期,江湖再见!!!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。