第47集:面向对象20_多态、内存分析深化(模拟servlet中方法的调用)
-
示例代码
package com.test047; public class HttpServlet { public void doGet(){ System.out.println("doGet"); } public void service(){ System.out.println("service"); doGet(); //此处相当于this.doGet(),调用的是子类MyServlet重写的方法。 } }
package com.test047; public class MyServlet extends HttpServlet { public void doGet(){ System.out.println("MyServlet.doGet()"); } }
package com.test047; public class Test { public static void main(String[] args){ HttpServlet s = new MyServlet(); s.service(); } }
-
内存分析
-
注意:
每个普通方法(甭管有参无参)里面,都有this和super两个隐式参数。
假如doGet是静态方法,结果就不是调用子类的doGet方法了,而是调用父类的doGet方法。
package com.test public class HttpServlet { public void service(){ System.out.println("service"); doGet(); } public static void doGet(){ System.out.println("doGet"); } } class MyServlet extends HttpServlet { public static void doGet(){ System.out.println("MyServlet.doGet()"); } public static void main(String[] args){ HttpServlet a = new MyServlet(); a.service(); } }
第48集:面向对象21_抽象类、抽象方法
抽象方法特点
只声明了方法,同时使用了abstract修饰,没有方法体!必须要子类来重写!抽象类
包含抽象方法的类,必须设计成抽象类!-
抽象类的使用要点
通过抽象类,可以避免子类设计的随意性。
抽象类不能实例化,及不能用new来实例化抽象类。
抽象类可以包含属性、方法、构造方法。但是构造方法不能用来new实例,只能用来被子类调用。
抽象类只能用来继承。
抽象方法必须被子类实现。
抽象类中可以有不抽象的方法。
public class Test { public static void main(String[] args){ Animal a = new Cat(); a.breath(); } }
public abstract class Animal { String str; public abstract void run(); public void breath(){ System.out.println("呼吸"); run(); } public Animal(){ System.out.println("动物"); } } class Cat extends Animal{ public void run(){ System.out.println("猫步"); } class Dog extends Animal{ public void run(){ System.out.println("狗跑"); } } }
第49集:面向对象_22_接口详解
抽象程度对比
普通类:只有具体实现
抽象类:具体实现和规范(抽象方法) 都有!
接口:只有规范!
为什么需要接口?
为了实现多继承【注意,类只有单继承,但Java能通过接口实现多继承】
接口是两个模块之间通信的标准,通信的规范。如果能把你要设计的系统之间模块之间的接口定义好,就相当于完成了系统的设计大纲,剩下的就是添砖加瓦的具体实现了。大家在工作以后,做系统时往往就是使用“面向接口”的思想来设计系统。
接口和抽象类的区别?
接口就是比“抽象类”还“抽象”的“抽象类”,可以更加规范的对子类进行约束。全面地专业地实现了:规范和具体实现的分离。
抽象类还提供某些具体实现,接口不提供任何实现,接口中所有方法都是抽象方法。接口是完全面向规范的,规定了一批类具有的公共方法规范。
如何定义接口?
访问修饰符:只能是public或默认。
接口名:和类名采用相同命名机制
extends:接口可以多继承
常量:接口中的属性只能是常量,总是:public static final 修饰。不写也是。
-
方法:接口中的方法只能是:public abstract。 省略的话,也是public abstract.
格式: [访问修饰符] interface 接口名 [extends 父接口1,父接口2…] { 常量定义 方法定义 }
接口的本质
从接口的实现者角度看,接口定义了可以向外部提供的服务。
从接口的调用者角度看,接口定义了实现者能提供那些服务。
接口就是规范,定义的是一组规则,体现了现实世界中“如果你是…则必须能…”的思想。如果你是天使,则必须能飞。如果你是汽车,则必须能跑。如果你好人,则必须干掉坏人;如果你是坏人,则必须欺负好人。
接口的本质是契约,就像我们人间的法律一样。制定好后大家都遵守。
接口的精髓,是对对象的抽象,最能体现这一点的就是接口。为什么我们讨论设计模式都只针对具备了抽象能力的语言(比如c++、java、c#等),就是因为设计模式所研究的,实际上就是如何合理的去抽象。
接口使用要点
子类通过implements来实现接口中的规范
接口不能创建实例,但是可用于声明引用变量类型。
一个类实现了接口,必须实现接口中所有的方法,并且这些方法只能是public的。;
接口中只能包含静态常量、抽象方法,不能有普通属性、构造方法、普通方法。
接口完全支持多继承。和类的继承类似,子接口扩展某个父接口,将会获得父接口中所定义的一切。
package com.test049;
public interface MyInterface {
//接口中只有常量和抽象方法
public static final String MAX_GREAD = "GIRL";
int MAX_SPEED = 123;
public abstract void test01();
int test02(int a,int b);
}
interface Attack {
void attack();
}
class Plane implements Flyable{
public void fly(){
System.out.println("fly");
}
}
class Man implements Flyable{
public void fly(){
System.out.println("man fly");
}
}
class Stone implements Flyable,Attack{
public void fly(){
System.out.println("sss");
}
public void attack(){
System.out.println("333");
}
}
package com.test049;
public interface Flyable {
int MAX_SPEED = 11000;
int MIN_HEIGHT = 1;
void fly();
}
package com.test049;
public class Test {
public static void main(String[] args){
Flyable f = new Stone();
f.fly();
}
}
package com.test049;
public interface InterfaceA {
void aaa();
}
interface InterfaceB{
void bbb();
}
interface InterfaceC extends InterfaceA,InterfaceB{
void ccc();
}
class TestClass implements InterfaceC{
public void aaa(){
}
public void bbb(){
}
public void ccc(){
}
}
第50集:面向对象23_回调的实现、模板方法模式
###CallBack/Hook作用
在写到某一步骤,不知道咋写时,留出地方让别人写
###模板方法模式
package com.test050;
public class MyFrame {
void paint(){
System.out.println("CallBack");
}
}
package com.test050;
public class PaintFrame {
public static void drawFrame(MyFrame f){
System.out.println("1");
System.out.println("2");
System.out.println("3");
//画窗口
f.paint();
System.out.println("5");
}
}
class GameFrame01 extends MyFrame{
public void paint(){
System.out.println("Game01");
}
}
package com.test050;
public class Test {
public static void main(String[] args){
PaintFrame.drawFrame(new GameFrame01());
}
}
第51集:面向对象24_内部类详解
内部类的定义(innerclasses)
一般情况,我们把类定义成独立的单元。有些情况下,我们把一个类放在另一个类的内部定义,称为内部类。
内部类的作用
内部类提供了更好的封装。只能让外部类直接访问,不允许同一个包中的其他类直接访问【注意,并非不可访问】。
内部类可以直接访问外部类的私有属性,内部类被当成其外部类的成员。 但外部类并不能直接访问内部类的内部属性。
内部类的使用场合
由于内部类提供了更好的封装特性,并且可以很方便的访问外部类的属性。所以,通常内部类在只为所在外部类提供服务的情况下优先使用。
内部类的分类
-
成员内部类(可以使用private、proteted、public任意进行修饰。 类文件:外部类$内部类.class)
-
非静态内部类(外部类里使用非静态内部类和平时使用其他类没什么不同)
非静态内部类必须寄存在一个外部类对象里。因此,如果有一个非静态内部类对象那么一定存在对应的外部类对象。 非静态内部类对象单独属于外部类的某个对象。
-
非静态内部类可以使用外部类的成员,但是外部类不能直接访问非静态内部类成员。
class outer { String type; class inner { String type; void HelloWorld(){ System.out.println("Hello World"); } } } public class test { public static void main(String[] args){ //HelloWorld a = new HelloWorld(); //不行 outer a = new outer(); outer.inner b = a.new inner(); //可行 b.HelloWorld(); } }
class outer { String type; class inner { String type; void HelloWorld(){ //System.out.println(type);//指inner的type //System.out.println(this.type);//指inner的type //System.out.println(outer.this.type);//指outer的type //若inner和outer无重名冲突,直接type就可以了 } } }
非静态内部类不能有静态方法、静态属性、静态初始化块。【即普通成员内部类只能有普通的方法和属性】
静态成员不能访问非静态成员:外部类的静态方法、静态代码块不能访问非静态内部类,包括不能使用非静态内部类定义变量、创建实例。
-
成员变量访问要点:
内部类里方法的局部变量:变量名
内部类属性:this.变量名
外部类属性:外部类名.this.变量名
-
内部类的访问:
外部类中定义内部类:new InnerClass()
-
外部类以外的地方使用非静态内部类:
Outer.inner varname = OuterObject.new Inner()
-
2. 静态内部类
1. 定义方式:
static class ClassName {
//类体
}
1. 使用要点:
1. 当一个静态内部类对象存在,并不一定存在对应的外部类对象。 因此,静态内部类的实例方法不能直接访问外部类的实例方法。
2. 静态内部类看做外部类的一个静态成员。 因此,外部类的方法中可以通过:静态内部类.名字 访问静态内部类的静态成员。通过 new 静态内部类()访问静态内部类的实例。
3. 在外部类的外面创建静态内部类:
Outer.StaticInner aInner = new Outer.StaticInner();
-
匿名内部类
适合那种只需要使用一次的类。比如:键盘监听操作等等。语法:
new 父类构造器(实参类表) 实现接口 () { //匿名内部类类体! }
this.addWindowListener(new WindowAdapter(){ @Override public void windowClosing(WindowEvent e) { System.exit(0); } });
-
局部内部类
定义在方法内部。作用域只限于本方法。用的非常少。
示例代码
package test051;
//import test051.Face.Nose;
public class Outer {
public static void main(String[] args){
//非静态内部类调用
Face a = new Face();
Face.Nose n = a.new Nose();
n.breath();
//静态内部类调用
Face.Ear m = new Face.Ear();
m.listen();
}
}
class Face {
int type;
String shape = "瓜子脸";
static String color = "red";
class Nose{
void breath(){
System.out.println("呼吸");
}
}
static class Ear{
void listen(){
//System.out.println(shape);//不可访问外部类普通属性
System.out.println("我在听");
//System.out.println(color);//可访问外部类静态属性
}
}
}