您的位置:首页 > 职场人生

黑马程序员---java学习笔记之面向对象:继承

2013-12-15 12:10 363 查看
------- android培训java培训、期待与您交流! ----------
1、继承的两个好处:

a):提高代码的复用性;

b):继承使类与类之间产生了关系,有了这个关系,才有了多态的特性。

2、怎么判断两个类是否有继承关系?

那就看假设的子类是否具备假设的其父类的所有属性及功能,如果是就可以继承,不是就不可以继承。

3、java不支持多继承,但支持多实现和多层继承。为什么不支持多继承呢?因为如果多个父类中有相同名字的函数时,子类调用该函数就无法辨别是调用的哪个父类的该函数。

4、在使用继承体系时,查阅父类的功能,创建子类的对象。

5、类与类之间的四种关系:

a):继承,即“is a”的关系,某类事物是另一类事物中的一员;

b):聚集,即“has a”的关系,两事物有共同的部分,我中有你的一部分,你中有我的一部分;

c):聚合,举个例子,就是球员和球队之间的关系;

d):组合,人体和双手,人体和心脏之间的关系,比聚合的关系更紧密。

6、当创建子类的对象时,需要把子类class文件加载进内存,但是加载子类class文件进内存之前,会把其父类的class文件先加载进内存。

7、子类和父类允许用同名变量。下面是示例:

class Fu
{
int num = 4;
}
class Zi extends Fu
{
int num = 5;
}

public class Test {
public static void main(String[] args) {

Zi z = new Zi();

System.out.println(z.num);
}

}
打印结果为5,即子类的变量num值。假设子类Zi并没有num属性

class Fu
{
int num = 4;
}
class Zi extends Fu
{
//int num = 5;
}

public class Test {
public static void main(String[] args) {

Zi z = new Zi();

System.out.println(z.num);
}

}
打印的结果为4,即父类的变量num值。

8、函数特性之一:重写(覆盖)。

当子类出现和父类一模一样的函数时,当用子类对象的引用去调用该函数时,执行的是子类的该函数。这叫做重写或者覆盖。

class Fu
{
public void show()
{
System.out.println("Fu show");
}

}
class Zi extends Fu
{
public void show()
{
System.out.println("Zi show");
}
}

public class Test {
public static void main(String[] args) {

Zi z = new Zi();

z.show();
}

}
打印输出的是“Zi show”

重写就是子类保留父类中某函数的功能并重写该函数的内容。

使用重写时的注意事项:

a):子类重写的函数的访问权限应该大于等于父类中被重写的该函数的访问权限。但是当父类中被重写的函数时private时,即使子类中重写的该函数的权限符合要求,这也不叫重写;

b):子类中静态函数只能重写父类中的静态函数,但是这种重写在多态中不能起到覆盖的作用

重写与重载的区别:

重写要求子父类中该函数一模一样,包括返回值(如果子类中的某函数与父类中某函数同名且参数列表一样但返回值类型是不一样的,这是不被允许的),而重载要求函数名相同但参数列表不一致;

9、继承在构造函数中的体现。

a):子父类的构造函数不能够覆写。为什么?我们知道覆写的函数要求是子父类的两函数一模一样(函数名+返回值+参数列表),但是子父类构造函数的名字是不可能一样的。

b):子类中至少会有一个构造函数要访问到父类的构造函数。这种思想是通过java子类构造函数代码中显式或隐式的super语句实现的。super语句或者this语句必须放在构造函数的第一句,用于子父类构造函数间的调用或者同一类中构造函数间的调用。另外需注意的是,并不是子类所有的构造函数的第一句代码就是super语句,当有this语句时,子类中的该构造函数可以没有super语句,但是子类中至少要有一个构造函数访问到父类的构造函数。

为什么子类对象一定要访问父类的构造函数?因为子类对象继承了父类的属性,同时也要继承父类对这些属性的初始化值,父类构造函数就是对这些属性进行初始化的构成,所以子类实例化的时候一定要访问父类的某个构造函数。

10、子类实例化过程中不仅会访问到父类中的构造函数,还会访问到父类中的另一块有初始化作用的构造代码块。示例如下:

class Fu
{
{
System.out.println("构造代码块运行");
}
}
class Zi extends Fu
{
}

public class Test {
public static void main(String[] args) {

Zi z = new Zi();
}

}
运行结果为:



11、final修饰符

a):可以用来修饰类,方法和变量;

b):当final修饰某类的时候,该类就不能被继承。类不能被继承,就可以保证该类的封装性,因为类不能被继承就不能被其子类中的方法覆盖,保证了该类的封装性;

c):final修饰方法的时候,该方法就不能被复写,这保证了该方法的封装性;

d):final既可以修饰成员变量,又可以修饰局部变量。用final修饰的数据只能被赋值一次,主要是用来描述那些固定的数据;

public class Test {

final int i;
Test()
{
i = 1;
System.out.println(i);
}
public static void main(String[] args) {

Test z = new Test();
}

}
上述代码中说明,i的默认初始值并不算是被赋值。

e):内部类定义在类中的局部位置时,该类只能访问该局部被final修饰的局部变量。

12、抽象类的特点:

a):抽象方法一定在抽象类中;

b):抽象方法和抽象类要用abstract修饰;

c):抽象被不能被创建对象,因为即使创建对象后,调用抽象方法也是没有意义的,抽象方法没有方法体;

d):某抽象类中的抽象方法要被使用,就需要由继承该抽象类的子类去覆盖所有的抽象方法后创建子类对象然后调用重写的方法。如果某抽象类的子类只是覆盖了该抽象类中一部分的抽象方法,那么该子类也是抽象的。

e):抽象类中可以没有抽象方法,但含有抽象方法的类中必须是抽象的。

下面是做的一些关于抽象类的一些小实验:

abstract class Personn
{
abstract void show();
public static void speak()
{
System.out.println("say your name");
}
}

public class AbstractTest {

public static void main(String[] args) {
// TODO Auto-generated method stub
Personn.speak();

}

}
运行结果为“say your name”

由上述代码可知,抽象类中可以含有不抽象的方法,另外,由于抽象类不能够实例化,调用该抽象类中的非抽象方法就需要将该非抽象方法设置为静态的,采用“类名.方法"的形式访问。但调用抽象类中的非抽象方法不一定总需要将其设为静态的,看下面的示例。

abstract class Personn
{
abstract void show();
public void speak()
{
System.out.println("say your name");
}
}
class Studentt extends Personn
{
void show()
{

}

}

public class AbstractTest {

public static void main(String[] args) {
// TODO Auto-generated method stub
new Studentt().speak();

}

}
运行成功。这说明在有了继承的概念后,即使抽象类中非抽象方法不设置为静态的,通过对其子类调用该非抽象方法,该抽象方法也可以被访问执行。

某类中方法被调用方式总结:

a):创建该类对象,使用”对象.方法”的方式调用,前提是类可创建对象;

b):使用”类名.方法“的方式调用,前提是被调用的方法是静态的;

c):通过继承由子类对象调用,在类不可创建对象,被调用方法也是非静态的,此时这种方法就会很有效。

13、对某些关键字的总结

a):将类设置成不能实例化有两种方式:将该类的构造函数设置为private的;用abstract修饰符修饰该类。

b):final修饰的类不能被继承。

14、模板方法设计模式

当定义功能时,功能的一部分是确定的,但是还有一部分是不确定的。不确定的部分就暴露出去,尤其子类去重写。下面是示例:

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 i = 0; i < 4000; i++ )
System.out.println(i);
System.out.println();
}
}

public class Test {

public static void main(String[] args) {
new SubTime().getTime();

}

}
类GetTime的getTime方法中运行代码是不确定的。所以将它定义为另一个函数,由子类的方法去重写它!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: