黑马程序员_Java基础_抽象类,模板设计模式,接口,内部类,多态
来源:互联网 发布:刷q币软件 编辑:程序博客网 时间:2024/05/25 18:09
1,抽象类的特点:
(1)抽象方法一定在抽象类中。
(2)抽象方法和抽象类必须被abstract关键字修饰。
(3)抽象类不可以用new创建对象。因为抽象方法没有意义。
(4)抽象类中的抽象方法要被使用,必须由子类复写起所有的抽象方法后,建立子类对象调用。
如果子类只覆盖了部分抽象方法,那么该子类还是一个抽象类。
2,抽象类和一般的类没有太大的不同,只不过是抽象类中多了一些不明确的东西,也就是抽象方法。所以导致抽象类不能实例化。
3,抽象类中也可以不定义抽象方法,这样做仅仅是为了不让该类建立对象。
4,抽象类和方法是使用abstract来表示的,abstract不能和final,private,static关键字共存。
原因是:被final修饰的类不能有子类,而被acstract修饰的类一定要有子类,它一定是一个父类。抽象类中的抽象方法如果是私 有的,那么子类就不知道这些方法,就无法复写这些方法,而抽象方法是一定要被子类复写的。如果static修饰抽象方法,那么就可以不建立对象 ,直接通过抽象类的类名访问抽象方法,这样访问的方法是没有任何意义的。
5,注意:抽象类中是有构造函数的,因为抽象类是一个父类,要给子类提供实例的初始化。
示例:假设定义一个员工类,包括姓名,年龄,工资。经理也是员工,但是和普通员工的工作方法不一样,但是经理除了拥有工资还拥有奖金,bounds,这时候就可以将员工类定义成抽象的,经理和普通员工都继承这个抽象的员工类。
//定义一个抽象员工类abstract class Employee {private String name;private String id;private double pay;Employee(String name, String id, double pay) {this.name = name;this.id = id;this.pay = pay;}public abstract void work();}// 经理类继承自员工class Manager extends Employee {// 经理除了拥有工资外还拥有额外的奖金private int bonus;Manager(String name, String id, double pay, int bonus) {super(name, id, pay);this.bonus = bonus;}// 重写经理的工作方式public void work() {System.out.println("manager work");}}// 普通员工也继承自员工类class Pro extends Employee {Pro(String name, String id, double pay) {super(name, id, pay);}// 普通员工重写普通员工的工作方法public void work() {System.out.println("pro work");}}
6,抽象的一个小应用:模板方法设计模式
模板方法设计模式是指:当在定义功能的时候,功能的一部分是确定的,一部分是不确定的,而确定的部分在调用不确定的部分,这时候我们可以将不确定的部分暴露出去,让他的子类来完成。
示例:定义一个获取程序运行时间的模板,通过获取开时的时间和结束的时间,将两个事件相减就得到程序的运行时间。
abstract class GetTime {// 定义获取时间的方法public final void getTime() {long start = System.currentTimeMillis();runcode();long end = System.currentTimeMillis();System.out.println("程序运行了" + (end - start) + "毫秒");}public abstract void runcode();}class SubTime extends GetTime {// 计算这段代码的运行时间public void runcode() {for (int x = 0; x < 4000; x++) {System.out.print(x);}}}class Demo {public static void main(String[] args) {SubTime st = new SubTime();st.getTime();}}abstract class GetTime {// 定义获取时间的方法public final void getTime() {long start = System.currentTimeMillis();runcode();long end = System.currentTimeMillis();System.out.println("程序运行了" + (end - start) + "毫秒");}public abstract void runcode();}class SubTime extends GetTime {// 计算这段代码的运行时间public void runcode() {for (int x = 0; x < 4000; x++) {System.out.print(x);}}}class Demo {public static void main(String[] args) {SubTime st = new SubTime();st.getTime();}}
示例:定义一个人的类,拥有年龄,姓名属性。学生和工人也是人,都继承自人这个类,那么学生和工人就拥有了姓名和年龄的属性。每个人都有自己的工作要做,学生工作是学习java,工人的工作是生产产品。学生还有学习外语的能力,并不是所有人都必须会说外语,比如工人就不一定了。
interface SpeakOther {public abstract void speakEnglish();}abstract class Person {String name;int age;Person(String name, int age) {this.name = name;this.age = age;}public abstract void work();}class Student extends Person implements SpeakOther {Student(String name, int age) {super(name, age);}public void work() {System.out.println("我是学生,我的工作是学习java");}public void speakEnglish() {System.out.println("我是学生,我还会说英语");}}class Worker extends Person {Worker(String name, int age) {super(name, age);}public void work() {System.out.println("我是工人,我的工作是生产商品");}}
示例:定义一个动物类,动物包括吃的功能,猫继承该类,狗也继承该类,同时猫具有捉老鼠的功能,狗具有看门的功能。通过多台调用各自的功能。
abstract class Animal {public abstract void eat();}class Cat extends Animal {public void eat() {System.out.println("猫吃鱼");}public void catchMouse() {System.out.println("猫捉老鼠");}}class Dog extends Animal {public void eat() {System.out.println("狗吃骨头");}public void lookHouse() {System.out.println("狗看房子");}}class AnimalDo {public void doEat(Animal a) {a.eat();/* * if (a instanceof Cat) { Cat c2 = (Cat)a; c2.catchMouse(); } if (a * instanceof Dog) { Dog d2 = (Dog)a; d2.lookHouse(); } */}}class DuotaiDemon {public static void main(String[] args) {AnimalDo ad = new AnimalDo();ad.doEat(new Cat());ad.doEat(new Dog());// Animal a = new Cat(); 这种方式叫做类型的提升,向上转型// a.eat();// Cat c = (Cat)a; 当要使用猫的特有方法时,使用强制类型转换// c.catchMouse();// function(new Cat());// function(new Dog());// 错误操作:Animal a = new Animal()// Cat c = (Cat)a;}/* * public static void function(Animal a1) { a1.eat(); if (a1 instanceof Cat) * { Cat c2 = (Cat)a1; c2.catchMouse(); } if (a1 instanceof Dog) { Dog d2 = * (Dog)a1; d2.lookHouse(); } } */}
举一个多态的实际应用:
/* 需求:定义一个主板,用户通过网卡上网,通过声卡听音乐,当然还可以添加其他卡实现其他功能。 * 多态增强程序的扩展性 */class MainBoard {public void run() {System.out.println("mainboard run...");}/* * public void useNetCard(NetCard nd) { nd.open(); nd.close(); * * 到此为止程序的扩展性并不好,因为当我还要加一个声卡听歌的时候,我必须还要 * 在增加一个useSongCard(SongCard()),如果在实际开发中这样的话,第二次增加功能时 * 代码还需要大篇幅修改,很麻烦。我们发现不管增加什么功能,他们的共性是open和close * ,因此解决方法是增加接口,接口中只提供open和close方法,具体怎么实现则是子类的问题了。 */public void useFunction(Pci p) { /*当把网卡传进来的时候,相当于Pci p = new NetCard(); * 父类引用指向子类对象,多态性; */p.open();p.close();}} /*这样来实现的话在以后如果想增加什么新的功能的话,MainBoard类就不需要再做修改,相当于电脑主板如果想增加什么硬件的话就在也不需要动主板,而直接把所要添加的硬件如声卡,网卡,直接插到主板所对外提供的声卡插槽和网卡插槽就可以了,这样就减小了主板和网卡,声卡的耦合性了,既相互之间的依赖关系不在呢那么强了。*/interface Pci {public abstract void open();public abstract void close();}class NetCard implements Pci {public void open() {System.out.println("netcard open...");}public void close() {System.out.println("netcard close...");}}class SongCard implements Pci {public void open() {System.out.println("songcard open...");}public void close() {System.out.println("songcard close...");}}class MainBoardExap // 相当于客户端{public static void main(String[] args) {MainBoard mb = new MainBoard();mb.run();// mb.useNetCard(new NetCard());mb.useFunction(new NetCard());mb.useFunction(new SongCard());}}
1,内部类顾名思义就定义在一个类的内部的类。
2,内部类的使用规则是:(1)内部类可以直接访问外部类的成员,包括自有成员。(2)外部类如果想要访问内部类的成员,必须先建立内部类的对象。
内部类定义在外部类的成员位置时而且非私有,在外部其他类中的访问格式是: 外部类名.内部类名 变量名 = 外部类对象.内部类对象;Outer.Inner in = new Outer().new Inner();
3,当内部类出现在外部类的成员位置上时,就能被成员修饰符修饰,比如下面出现的Inner类可以被private修饰;
4,内部类可以不仅可以定义成私有,还可以定义成静态,这是外部类不能做到的。当把内部类定义成静态的时候要注意:(1)当内部类中定义了静态成员,那么该内部类必须是静态的。(2)当外部类的静态成员访内部类的时候,该内部类也要定义成静态的。
在外部其他类中访问static内部类的静态成员格式:Outer.Inner.function();
class Outer{ static int num = 99; static class Inner //内部类可以加private修饰符,外部类不可以; { //int num = 888; public static void method() { //int num = 7777; //当内部类中存在与外部类相同的成员变量时,会先从内部开始寻找 //System.out.println("Inner Class"); //内部类存在与外部类相同的成员变量时访问外部成员变量可以这么做, 再成员变量前加外部类的类名和this //System.out.println(this.num); //System.out.println(Outer.this.num); System.out.println(num); } } public void function() { Inner in = new Inner(); in.method(); }}class InnerClassDemon{ public static void main(String[] args) { // Outer o = new Outer(); // o.function(); //内部类定义的格式如下:(格式记住就可以了) //Outer.Inner oi = new Outer().new Inner(); //oi.method(); //new Outer.Inner().method();//当method方法为非静态时,有这种访问格式访问 //Outer.Inner.method(); //当method方法为静态时,用这种格式访问; }}
5,内部类还可以定义在外部类的局部,也就是外部类的方法的内部。
注意:(1)局部内部类可以直接访问外部类的成员,因为持有外部类的引用。
(2)局部内部类不可以直接访问局部的成员,也就是不能直接访问外部类的方法中的成员,除非局部成员是final的。
示例:关于局部内部类的使用举例
(3)局部内部类是不可以定义成静态的,原因是static是成员修饰符,不可以修饰局部。
(4)如果局部内部类内的成员是静态的,那么该内部类也必须是静态的,而static不能修饰局部,所以这样以来局部内部类中的成员也是不可以用static修饰的。
class Outer3{ int x = 9; public void show(final int n) {//这样才可以被Inner3类中的成员访问; //n ++;错误,不能会n进行操作; final int y = 88; class Inner3 { public void function3() { System.out.println(n); System.out.println("inner3 method___" + x +"___" + y);//这里的x相当于Outer3.this.x //因为y在show方法内部,这里的y必须声明为final型,否则编译出错 } }//注意:内部类在局部时,它里面的成员不能是静态,因为如果成员是静态则该内部类也必须是静态,而static //是成员修饰符,static class Inner3不是成员,是show方法的局部,不能修饰局部; new Inner3().function3(); }}class InnerClassDemon3{ public static void main(String[] args) { Outer3 o3 = new Outer3(); //o3.show(); o3.show(6); o3.show(7);//进栈出栈的原理; }}
6,匿名内部类:匿名内部类其实就是内部类的简写格式。定义匿名内部类的前提是:该类继承一个类或者一个接口 。匿名内部类的格式:new 父类名或接口名() {定义子类的内容}
匿名内部类可以理解成一个匿名的子类对象,也可以理解成带内容的对象。
使用匿名内部类时要注意:匿名内部类本来就是为了简化代码量,当一个内部类继承的接口中含有三个以上的抽象方法的时候,不建议使用匿名内部类,因为在书写是你需要在匿名内部类中实现接口中所有的抽象方法,阅读性会很差,要实现功能的时候却只用到这些抽象方法中的一个。
下面提供一个匿名内部类使用的代码:
interface Inter{ public abstract void show(); public abstract void show2(int n);}class Outer2{ /* class Inner2 implements Inter { public void show() { System.out.println("show method"); } } */ public void function2() { //new Inner2().show(); Inner in = new Inter() { //这一句相当:Inner in = new Inner() --->多态性 public void show() { System.out.println("show method2"); } public void show2(int n) { System.out.println("show2 method" + n); } public void show3() { System.out.println(12345); }//这就相当于子类的特有方法,如果在大括号外调用show3()就会出错,因为new Inner()具有多态性, //父类中没有show3这个方法,所以不能调用子类特有的方法,当然这里也不能进行强制类型转换,因为 //该类跟部就没有名字,也就没有子类类型。 }; in.show(); //该部分就是上面注释掉的绿色部分 //in.show3();编译会出错,原因是42--44行; new Inter() { public void show() { System.out.println("show method2"); } public void show2(int n) { System.out.println("show2 method___" + n); } }.show2(99); }}class InnerClassTest{ public static void main(String[] args) { Outer2 o2 = new Outer2(); o2.function2(); }}
- 黑马程序员_Java基础_抽象类,模板设计模式,接口,内部类,多态
- 黑马程序员—Java面向对象(抽象类、模板方法设计模式、接口、多态、内部类)
- 黑马程序员-多态(抽象类、组合设计模式、接口)、内部类学习
- 黑马程序员_面向对象2_(继承、多态、抽象类abstract、接口interface、内部类)
- 黑马程序员_Java基础Day09(上)_内部类(Done)
- 黑马程序员_JAVA基础2_内部类,异常1
- 黑马程序员-抽象类、接口、内部类
- 黑马程序员_面向对象二(继承,多态,抽象类abstract,接口Interface,内部类)
- 黑马程序员_JAVA基础_继承,抽象和接口
- 黑马程序员_java入门_内部类
- 黑马程序员——java基础--抽象类、接口、多态、内部类、异常、包
- 黑马程序员_java 继承_抽象类_接口
- 黑马程序员_抽象类与模板方法设计模式
- 黑马程序员_抽象类&模板设计模式
- 黑马程序员_JAVA基础_内部类,匿名内部类,异常
- 黑马程序员_面向对象(2) 接口&抽象类&内部类
- 黑马程序员_JAVA基础_抽象类与接口的关系
- 黑马程序员_java面向对象_抽象类和接口
- Spring IOC容器
- J2ee和.net心得
- 阿里巴巴2014研发工程师实习生面试经历
- Java基础巩固之线程学习
- UVa 10110 - Light, more light
- 黑马程序员_Java基础_抽象类,模板设计模式,接口,内部类,多态
- ComputeLoanUsingInputDialog
- js动态移动滚动条至底部
- 未毕业先工作(第一篇)
- 实际用户ID,有效用户ID及设置用户ID
- 数据库关系为多态关联时,适当使用反模式
- Python下pefile的使用
- Mysql Limit操作及优化
- LigerUI编辑表格组件单元格校验问题