【黑马程序员】 java笔记——抽象类
来源:互联网 发布:windows10下安装mysql 编辑:程序博客网 时间:2024/06/05 00:29
抽象类
一、面向对象(抽象类1)
当多个类中出现相同功能,但是功能主体不同,这是可以进行向上抽取的。这时,只抽取功能定义,而不抽取功能主体。
抽象:看不懂。
抽象类的特点:
1、 抽象方法一定在抽象类中。
2、 抽象方法和抽象类都必须被abstract关键字修饰。
3、 抽象类不可以用new创建对象。因为调用抽象方法没意义。
4、 抽象类中的抽象方法要被使用,必须由子类复写起所有的抽象方法后,建立子类对象调用。
如果子类只覆盖了部分抽象方法,那么该子类还是一个抽象类。
二、面向对象(抽象类2)
抽象类和一般类没有太大的不同。
该如何描述事物,就如何描述事物,只不过,该事物出现了一些看不懂的东西。
这些不确定的部分,也是该事物的功能,需要明确出现,但是无法定义主体。
通过抽象方法来表示。
抽象类比一般类多了个抽象函数,就是在类中可以定义抽象方法。
抽象类不可以实例化。
特殊:抽象类中可以不定义抽象方法,这样做仅仅是不让该类建立对象。
1.抽象类
用abstract 修饰的类被称为抽象类。所谓抽象类就是没有具体实例对象的类。
抽象类通常包括一个或多个抽象方法(只有方法说明,没有方法体),抽象类的子类必须完成父类定义的每一个抽象方法,除非该子类也是抽象类。
抽象类的主要用途是用来描述概念性的内容,这样可以提高开发效率,更好地统一用户“接口”。
2. 定义一个抽象类
abstract class 类名称
{
成员变量;
方法(); //定义一般方法
abstract 方法(); //定义抽象方法
}
说明:抽象类中可以包含有一般方法,也可以包含有抽象方法;对于抽象方法不用完成其代码实现,而在派生的子类中实现所有抽象方法。
3. 抽象类实现的例子
如前所述你可能对抽象类的概念有点模糊,下面举一个具体实例来作说明。
假设想设计一个形状(shape)的父类CShape,由此类可派生出圆形(circle),长方形(rectangle)于三角形(triangle)等几何形状的类。则父类于子类的派生关系描绘成如下图所示。
4.需求假设
假设这些几何形状均具有“颜色”(color)这个属性,因此可以把color这个数据成员,以及赋值color的方法均设计在父类里,让它继承给各个形状的子类较为方便,如此就不用在每一个几何形状的子类里,设计相同的程序代码来处理“颜色”这个属性的问题。
另外,如果想为每一个几何形状的类设计一个area()方法,用来显示几何形状的面积,因每种几何形状的面积计算方式并不相同,所以把area()方法的处理方式设计在父类里并不恰当,但每一个由CShape父类所派生出的子类又都需要用到这一个方法,因此可以在父类里只声明area()方法,而把area()方法处理的方法留在子类里来定义,也就是说,把area()声明成抽象方法即可解决这个问题。根据上述的概念,可编写出如下的父类程序代码:
abstract class CShape //定义抽象类{ protected String color; //数据成员 public void setColor(String str) { color=str; //一般的方法,用来赋值几何形状的颜色 } abstract void area();//抽象类内的抽象方法}class CRectangle extends CShape{ int width,height; publicCRectangle (int w,int h) { width=w; height=h; } public void area() { System.out.print(“color=“+color+”, “); System.out.print(“area=“+width*height); }} Public class app10-1{ public static void main (Stringargs[]){ CRetangle rect=newCRectangle(5,10); rect.setColor(“yellow”); rect.area(); CCircle cir=new CCircle(2.0) cir.setColor(“Green”); cir.area(); }}
抽象类
抽象方法的特征:
抽象方法需要使用abstract关键字修饰
抽象方法没有方法体
抽象方法在参数列表后面没有大括号,但有一个分号。
具有一个或多个抽象方法的类必须声明为抽象类。
抽象类的子类,有两条路可以走:
把父类所有抽象方法都实现完成,这样子类就不用再抽象了;
不实现,或者不实现所有抽象方法,那么对子类来说也有未完成的方法,那么子类也需要声明为抽象类。
抽象方法不能是静态的,也不能是private的,更不能是final的。与多态冲突的东西都不行。
抽象类是否可以有构造器:
思考:构造器是用来干什么的?与new使用创建实例对象。
思考:抽象类不能创建实例对象,那么它有构造器有没有用?
子类是不是需要调用父类构造器?需要,那么也就是说抽象类可以有构造器,而构造器是给子类构造器来用的。
abstract class A{ public A(String s) {} public abstract void fun();}abstract class B extends A{ public B() { super("hello"); } public void fun() { System.out.println("hello"); }}
抽象类是否可以不定义抽象方法?
抽象类可以不定义抽象方法,但很少有人这么做。
一个类如果有一到多个抽象方法,那么这个类必须声明为抽象类。
abstract关键字与什么关键字冲突?
private、static、final
如果你的方法中,存在以上任意一个修饰符,那么这个方法就不能是抽象方法。
在什么时候使用抽象类?
当你想调用一个方法,而这个方法的参数类型为抽象类类型!
public class Test{ public static void main(String[] args) { A a = new B(); abc(a); } // 该方法的参数类型为A类型 // A类型是抽象类 // 我们无法实例化A类型的对象 // 说明我们需要写一个A类的子类,然后实例化子类的对象, // 最后使用子类对象来调用abc方法。 public static void abc(A a) { } }abstract class A{ publicabstract void fun(); }class B extends A{ public void fun() { }}
当我们想使用abc()方法时,因为abc()方法的参数是A类的,而且A类是抽象类,那么我们就需要创建一个A类的子类类型对象,然后用这个对象来调用abc()方法。
1.创建A类的子类
2.创建子类对象
3.用这个对象来调用abc()方法
public class Test{ public static void main(String[] args) { /* 自己来写三个Waiter的子类,用每个子类的对象来调用fun()方法 */ } public static void fun(A a) { a.service(); } }abstract class Waiter { public abstract void fun1(); public abstract void fun2(); public void service() { fun1(); serv(); fun2(); } public void serv() { System.out.println("服务..."); } }
抽象类
可以有实例属性、静态属性
可以有构造器
可以有实例方法、抽象方法、静态方法
就是什么都可以有,就是不能有实例对象(不能创建对象)。
抽象类一般都会有抽象方法,即没有加工的地方。
抽象类、子类的变量和函数与父类的关系:
父类代码:
//父类,抽象类abstract public class A{ static{ System.out.println("A"); } int i; A(int i) { this.i = i; System.out.println("A "+i); } abstractpublicvoid f1(); abstractpublicvoid f2(); publicvoid f3() { System.out.println("A f3 "+i); }}
父类是个抽象类,可以有自己的数据成员,也可以有非abstarct的成员方法。但是不能被实例化。
子类1代码:
//子类, publicclass C1 extends A { C1(int i) { super(i); i++; System.out.println("C1 "+i); } publicvoid f1() { System.out.println("C1 f1 "+i); } publicvoid f2() { } publicvoid f3() { i=5; System.out.println("C1 f3 "+i); System.out.println("C1 f3 super "+super.i); super.f3(); }}
该子类C1实现了父类所有的方法,抽象和非抽象的。
子类2代码:
// 子类 publicclassC2 extends A { C2(int i) { super(i); // 必须在第一行,且 this.i=8; System.out.println("C2 "+this.i); } publicvoid f1() { } publicvoid f2() { System.out.println("C2 f2 "+i); } }
子类C2实现了父类的抽象方法。子类在继承抽象类时,必须实现抽象类中的所有抽象方法。
publicstaticvoid main(String[]args ) { System.out.println("main start"); C1 c1 = new C1(0); C2 c2 = new C2(0); System.out.println("new"); c1.f1(); c1.f2(); c1.f3(); System.out.println("c1 over"); c2.f1(); c2.f2(); c2.f3(); }
输出结果:
main start
A
A 0
C1 1
A 0
C2 8
new
C1 f1 0
C1 f3 5
C1 f3 super 5
A f3 5
c1 over
C2 f2 8
A f3 8
从整体上来说,我们知道从对象的内存角度来说,假设现在有一个父类Father,它里面的变量需要占用1M内存.有一个它的子类Son,它里面的变量需要占用0.5M内存。
现在通过代码来看看内存的分配情况:
Father f = new Father(); //系统将分配1M内存.
Son s = new Son(); //系统将分配1.5M内存,因为子类中有一个隐藏的引用super会指向父类实例,所以在实例化子类之前会先实例化一个父类,也就是说会先执行父类的构造函数.由于s中包含了父类的实例,所以s可以调用父类的方法。
1.C1 c1 = new C1(0);对应输出了A;A 0;C1 1;先输出A,这点同时验证了子类先初始化父类,再执行父类构造函数A 0;再子类的构造函数C1 1。
2.C2 c2 = new C2(0);对应输出了A 0;C2 8;看出父类初始化只有一次,当构造函数必须在执行一次。
3.子类c1实现了自己的f1、f2、f3,使用时就是使用的自己的实现;子类c2没有实现f3,调用父类的实现。但是只使用父类的方法,数据成员还是自己的,所有输出“A f3 8”。
- 【黑马程序员】 java笔记——抽象类
- 【黑马程序员】Java笔记——抽象类: abstract
- 黑马程序员——抽象类笔记
- 黑马程序员—JAVA抽象类
- 黑马程序员—抽象类
- 黑马程序员——Java练习笔记——抽象类和接口
- 黑马程序员——Java学习笔记 继承、抽象类和接口
- 黑马程序员——Java面向对象之抽象类 接口 内部类笔记
- 黑马程序员Java笔记——抽象类、接口、内部类(拾遗补录)
- 【黑马程序员】多态、抽象类、接口——Java复习笔记
- 黑马程序员——Java基础--抽象
- 黑马程序员——java抽象类详解
- 黑马程序员—JAVA基础之继承、抽象类、接口
- 黑马程序员----JAVA----抽象类----
- 《黑马程序员》java笔记->【03】关于抽象类
- 黑马程序员——Java基础---面向对象(继承_概述、关键字final、抽象类)(5) 分类: Java学习笔记
- 黑马程序员——抽象类
- 黑马程序员——抽象类&接口
- Difference between Stack and Heap memory in Java
- How to use ConcurrentHashMap in Java - Example Tutorial and Working
- 易混淆的字母
- nyoj-79-拦截导弹
- 关于日期2013-05-25T19:09:18.769+0800格式化
- 【黑马程序员】 java笔记——抽象类
- RGB图像灰度化
- 【ASP.Net MVC3 】使用Moq让单元测试变得更简单
- [回溯]23 out of 5 UVA 10344
- Java中的OutOfMemoryError和JVM内存结构
- How to override compareTo method in Java - Example Tutorial
- neo4j使用指南
- [转载]图像处理与计算机视觉:基础,经典以及最近发展
- JUC.Condition学习笔记