java继承2——类与继承(转)
一.你了解类吗?
在Java中,类文件是以.java为后缀的代码文件,在每个类文件中最多只允许出现一个public类,当有public类的时候,类文件的名称必须和public类的名称相同,若不存在public,则类文件的名称可以为任意的名称(当然以数字开头的名称是不允许的)。
在类内部,对于成员变量,如果在定义的时候没有进行显示的赋值初始化,则Java会保证类的每个成员变量都得到恰当的初始化:
1)对于 char、short、byte、int、long、float、double等基本数据类型的变量来说会默认初始化为0(boolean变量默认会被初始化为false);
2)对于引用类型的变量,会默认初始化为null。
如果没有显示地定义构造器,则编译器会自动创建一个无参构造器,但是要记住一点,如果显示地定义了构造器,编译器就不会自动添加构造器。注意,所有的构造器默认为static的。
下面我们着重讲解一下 初始化 顺序:
当程序执行时,需要生成某个类的对象,Java执行引擎会先检查是否加载了这个类,如果没有加载,则先执行类的加载再生成对象,如果已经加载,则直接生成对象。
在类的加载过程中,类的static成员变量会被初始化,另外,如果类中有static语句块,则会执行static语句块。static成员变量和static语句块的执行顺序同代码中的顺序一致。记住,在Java中,类是按需加载,只有当需要用到这个类的时候,才会加载这个类,并且只会加载一次。看下面这个例子就明白了:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
public class Test { public static void main(String[] args) throws ClassNotFoundException { Bread bread1 = new Bread(); Bread bread2 = new Bread(); }}class Bread { static{ System.out.println("Bread is loaded"); } public Bread() { System.out.println("bread"); }} |
运行这段代码就会发现"Bread is loaded"只会被打印一次。
在生成对象的过程中,会先初始化对象的成员变量,然后再执行构造器。也就是说类中的变量会在任何方法(包括构造器)调用之前得到初始化,即使变量散步于方法定义之间。
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
public class Test { public static void main(String[] args) { new Meal(); }}class Meal { public Meal() { System.out.println("meal"); } Bread bread = new Bread();}class Bread { public Bread() { System.out.println("bread"); }} |
输出结果为:
bread
meal
二.你了解继承吗?
继承是所有OOP语言不可缺少的部分,在java中使用extends关键字来表示继承关系。当创建一个类时,总是在继承,如果没有明确指出要继承的类,就总是隐式地从根类Object进行继承。比如下面这段代码:
|
1
2
3
4
5
6
7
8
9
10
11
|
class Person { public Person() { }}class Man extends Person { public Man() { }} |
类Man继承于Person类,这样一来的话,Person类称为父类(基类),Man类称为子类(导出类)。如果两个类存在继承关系,则子类会自动继承父类的方法和变量,在子类中可以调用父类的方法和变量。在java中,只允许单继承,也就是说 一个类最多只能显示地继承于一个父类。但是一个类却可以被多个类继承,也就是说一个类可以拥有多个子类。
1.子类继承父类的成员变量
当子类继承了某个类之后,便可以使用父类中的成员变量,但是并不是完全继承父类的所有成员变量。具体的原则如下:
1)能够继承父类的public和protected成员变量;不能够继承父类的private成员变量;
2)对于父类的包访问权限成员变量,如果子类和父类在同一个包下,则子类能够继承;否则,子类不能够继承;
3)对于子类可以继承的父类成员变量,如果在子类中出现了同名称的成员变量,则会发生隐藏现象,即子类的成员变量会屏蔽掉父类的同名成员变量。如果要在子类中访问父类中同名成员变量,需要使用super关键字来进行引用。
2.子类继承父类的方法
同样地,子类也并不是完全继承父类的所有方法。
1)能够继承父类的public和protected成员方法;不能够继承父类的private成员方法;
2)对于父类的包访问权限成员方法,如果子类和父类在同一个包下,则子类能够继承;否则,子类不能够继承;
3)对于子类可以继承的父类成员方法,如果在子类中出现了同名称的成员方法,则称为覆盖,即子类的成员方法会覆盖掉父类的同名成员方法。如果要在子类中访问父类中同名成员方法,需要使用super关键字来进行引用。
注意:隐藏和覆盖是不同的。隐藏是针对成员变量和静态方法的,而覆盖是针对普通方法的。(后面会讲到)
3.构造器
子类是不能够继承父类的构造器,但是要注意的是,如果父类的构造器都是带有参数的,则必须在子类的构造器中显示地通过super关键字调用父类的构造器并配以适当的参数列表。如果父类有无参构造器,则在子类的构造器中用super关键字调用父类构造器不是必须的,如果没有使用super关键字,系统会自动调用父类的无参构造器。看下面这个例子就清楚了:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
class Shape { protected String name; public Shape(){ name = "shape"; } public Shape(String name) { this.name = name; }}class Circle extends Shape { private double radius; public Circle() { radius = 0; } public Circle(double radius) { this.radius = radius; } public Circle(double radius,String name) { this.radius = radius; this.name = name; }} |
这样的代码是没有问题的,如果把父类的无参构造器去掉,则下面的代码必然会出错:

改成下面这样就行了:

4.super
super主要有两种用法:
1)super.成员变量/super.成员方法;
2)super(parameter1,parameter2....)
第一种用法主要用来在子类中调用父类的同名成员变量或者方法;第二种主要用在子类的构造器中显示地调用父类的构造器,要注意的是,如果是用在子类构造器中,则必须是子类构造器的第一个语句。
三.常见的面试笔试题
1.下面这段代码的输出结果是什么?
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
public class Test { public static void main(String[] args) { new Circle(); }}class Draw { public Draw(String type) { System.out.println(type+" draw constructor"); }}class Shape { private Draw draw = new Draw("shape"); public Shape(){ System.out.println("shape constructor"); }}class Circle extends Shape { private Draw draw = new Draw("circle"); public Circle() { System.out.println("circle constructor"); }} |
shape draw constructor
shape constructor
circle draw constructor
circle constructor
这道题目主要考察的是类继承时构造器的调用顺序和初始化顺序。要记住一点:父类的构造器调用以及初始化过程一定在子类的前面。由于Circle类的父类是Shape类,所以Shape类先进行初始化,然后再执行Shape类的构造器。接着才是对子类Circle进行初始化,最后执行Circle的构造器。
2.下面这段代码的输出结果是什么?
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
|
public class Test { public static void main(String[] args) { Shape shape = new Circle(); System.out.println(shape.name); shape.printType(); shape.printName(); }}class Shape { public String name = "shape"; public Shape(){ System.out.println("shape constructor"); } public void printType() { System.out.println("this is shape"); } public static void printName() { System.out.println("shape"); }}class Circle extends Shape { public String name = "circle"; public Circle() { System.out.println("circle constructor"); } public void printType() { System.out.println("this is circle"); } public static void printName() { System.out.println("circle"); }} |
shape constructor
circle constructor
shape
this is circle
shape
这道题主要考察了隐藏和覆盖的区别。
覆盖只针对非静态方法(终态方法不能被继承,所以就存在覆盖一说了),而隐藏是针对成员变量和静态方法的。这2者之间的区别是:覆盖受RTTI(Runtime type identification)约束的,而隐藏却不受该约束。也就是说只有覆盖方法才会进行动态绑定,而隐藏是不会发生动态绑定的。在Java中,除了static方法和final方法,其他所有的方法都是动态绑定。因此,就会出现上面的输出结果。
原文链接:
http://www.cnblogs.com/dolphin0520/p/3803432.html
java继承2——类与继承(转)的更多相关文章
- Java编程里类的继承
今天,我们将要讨论的内容是Java里面类的继承的相关概念. 说到继承,我相信大家都不陌生.生活中,子承父业,子女继承父母的财产,这就是继承.实际上,Java里的继承也是如此.对于一个类来说,它的数据成 ...
- java类为什么是单继承。类的继承,实现接口。
java中提供类与类之间提供单继承. 提供多继承会可能出现错误,如:一个类继承了两个父类,而两个父类里面都有show()方法. class Fulei1{ public void show(){ Sy ...
- java中阻止类的继承
1.使用final来修饰类 final表示这个类是继承树的末端,不能被继承. 2.将类的构造方法声明为private的,再提供一个static的方法来返回一个类的对象. JAVA语言要求继承时必须在构 ...
- [Java学习]面向对象-类的继承;方法覆盖
一.类的继承 实现方法: public Class SubClass extends SuperClass{ } 继承最基本作用: 代码重用. 继承最重要的作用: 方法可以重写. 关于类的继承: 子类 ...
- 【代码笔记】Java基础:类的继承(构造器)
在Java中,创建对象的格式为: 类名 对象名 = new 类名(): 如: 1 JFrame jf = new JFrame(); 一个对象被创建出来时,经常要先做一些事这个对象才能正常使用,也可以 ...
- JS原型继承和类式继承
前言 一个多月前,卤煮读了一篇翻译过来的外国人写的技术博客.此君在博客中将js中的类(构造)继承和原型继承做了一些比较,并且得出了结论:建议诸位在开发是用原型继承.文中提到了各种原型继承的优点,详细的 ...
- js原生设计模式——2面向对象编程之继承—new类式继承
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8&qu ...
- js原生继承之——类式继承实例(推荐使用)
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8&qu ...
- JS原型继承与类的继承
我们先看JS类的继承 <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> &l ...
随机推荐
- PHP5.3新特性
1.首先对之前滥用的语法进行了规范 众所周知PHP在语言开发过程中有一个很好的容错性,导致在数组或全局变量中包含字符串不使用引号是可以不报错的,很多业余的开发者因为懒惰而产生的安全问题十分严重,之所以 ...
- IT常用设备及服务器安全公告或漏洞地址pa安全预警微软安全公告 HP 安全公告AIX 安全公告REDHAT安全公告ORACLE 安全公告F5 安全公告 Cisco 安全公告Juniper 安全公告 VMware 安全公告IOS 安全公告
IT常用设备及服务器安全公告或漏洞地址: 微软安全公告 https://technet.microsoft.com/en-us/library/security/MS14-085 HP 安全公告 ht ...
- C# Timer使用方法示例
实例化一个timer: // 每5分钟执行一次,每次执行的间隔毫秒时长 System.Timers.Timer timer = new System.Timers.Timer(5*60*1000); ...
- HttpClient 解释
HttpClient:是一个接口 首先需要先创建一个DefaultHttpClient的实例 HttpClient httpClient=new DefaultHttpClient(); 发送GET请 ...
- 利用ARP和ICMP协议解释ping命令
一.MTU 以太网和IEEE 802.3对数据帧的长度都有限制,其最大值分别是1500和1492字节,将这个限制称作最大传输单元(MTU,Maximum Transmission Unit).如果IP ...
- Spring boot处理OPTIONS请求
一.现象从fetch说起,用fetch构造一个POST请求. fetch('http://127.0.0.1:8000/api/login', { method: "POST", ...
- [转]四种π型RC滤波电路
1.典型π型RC滤波电路 图7-27所示是典型的兀型RC滤波电路.电路中的Cl.C2是两只滤波电容,Rl是滤波电阻,Cl.Rl和C2构成一节π型RC滤波电路.由于这种滤波电路的形式如同字母π且采 ...
- 为anaconda的jupyter notebook设置初始化目录
在使用jupyter进行编程时,初始化目录可能不是自己想要的目录,那么下面讲解修改成自己想要的目录. 1) 在命令行中输入jupyter notebook --generate-config,会产生一 ...
- ASP.NET MVC 笔记
(从今天开始,还是换回默认的代码高亮插件吧...话说此篇仅供个人遗忘后查阅,木有详尽解释...) 1.Controller中的所有Action方法不限制返回值类型,返回值应该至少可以被ToString ...
- java.lang.IllegalStateException: The specified child already has a parent. You must call removeView
java.lang.IllegalStateException: The specified child already has a parent. You must call removeVi ...