Java_类和对象(完美总结)_转载_覆盖和隐藏的区别,覆盖就不能使用了,而隐藏提供全局方法名或者全局变量名还可以使用
转载自海子:http://www.cnblogs.com/dolphin0520/p/3803432.html
Java:类与继承
对于面向对象的程序设计语言来说,类毫无疑问是其最重要的基础。抽象、封装、继承、多态这四大特性都离不开类,只有存在类,才能体现面向对象编程的特点,今天我们就来了解一些类与继承的相关知识。首先,我们讲述一下与类的初始化相关的东西,然后再从几个方面阐述继承这一大特性。以下是本文的目录大纲:
一.你了解类吗?
二.你了解继承吗?
三.常见的面试笔试题
若有不正之处,请多多谅解并欢迎批评指正。
请尊重作者劳动成果,转载请标明原文链接:
http://www.cnblogs.com/dolphin0520/p/3803432.html
一.你了解类吗?
在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
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; } } |
这样的代码是没有问题的,如果把父类的无参构造器去掉,则下面的代码必然会出错:
- 上述错误是因为父类没有无参数的构造函数,而有参数的构造函数在子类中要加super才能表示调用了父类的有参数的构造函数;
- 而下面修改后的代码就是加了几个super;
- 当然如果父类有无参数的构造函数,子类调用父类的有参数的构造函数时不需要加super的;
改成下面这样就行了:
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" ); } } |
1 shape constructor
2 circle constructor
3 shape
4 this is circle // 其他方法可以被覆盖
5 shape // static方法无法被覆盖
这道题主要考察了隐藏和覆盖的区别(当然也和多态相关,在后续博文中会继续讲到)。
覆盖只针对非静态方法(终态方法不能被继承,所以就存在覆盖一说了),而隐藏是针对成员变量和静态方法的。这2者之间的区别是:覆盖受RTTI(Runtime type identification)约束的,而隐藏却不受该约束。也就是说只有覆盖方法才会进行动态绑定,而隐藏是不会发生动态绑定的。在Java中,除了static方法和final方法,其他所有的方法都是动态绑定。因此,就会出现上面的输出结果。
总结java中
1、方法的覆盖和隐藏:
一个大的原则:静态方法不能被覆盖。实例方法被覆盖,静态方法被隐藏。
被覆盖的方法只有覆盖它们的类才能访问它们,而访问被隐藏的方法是提供该方法的全局名(也就是这里的Shape.shape本来是被子类同名变量影藏的,但是由于提供了全局名字,因此可以访问)。
2、变量的隐藏:变量只会隐藏,方然静态的或者final的变量不允许被子类重定义,会报错;
总之:能被覆盖的方法(当然只能是动态方法),父类再怎么访问都访问不了;
而被隐藏的方法(当然只能是静态的方法)或者变量,引用全局的函数名或者变量名还可以访问;所谓全局就是:父类.方法或者父类.变量 。
Java_类和对象(完美总结)_转载_覆盖和隐藏的区别,覆盖就不能使用了,而隐藏提供全局方法名或者全局变量名还可以使用的更多相关文章
- JAVA基础复习与总结<一> 对象与类的概念_内部类_继承与多态
一.对象与类 类:类是一个模版,它描述了一类对象的行为和状态. class animal { private int color; private int size; public void eat ...
- C++中如何定义类和对象?
在C++语言中,对象的类型被称为类,类代表了某一批对象的共性和特征. 类是对象的抽象,而对象是类的具体实例.如同C中的结构体一样,我们要先定义一个结构体,再使用结构体去定义一个变量.同一个结构体可以定 ...
- Objective-C Runtime 运行时之一:类与对象(转载)
Objective-C语言是一门动态语言,它将很多静态语言在编译和链接时期做的事放到了运行时来处理.这种动态语言的优势在于:我们写代码时更具灵活性,如我们可以把消息转发给我们想要的对象,或者随意交换一 ...
- 人生苦短_我用Python_类与对象的概念_006
Python类与对象的概念类和对象--->万事万物都对象物以类聚.人以群分 --->?划分标准性别分 男女 中性成绩分 优秀 良好 不及格 类->根据类的属性来划分类的实例-> ...
- No1_8.类和对象2_Java学习笔记_对象
对象 /**** * *一.对象 *1.概念:对象是由类抽象出来的,对象可以操作类的属性和方法解决问题,了解对象的创建.操作和消亡很必要: *2.对象的创建: * a. new操作符创建:每实例化一个 ...
- 04737_C++程序设计_第4章_类和对象
例4.1 描述点的Point类. 例4.2 根据上面对Point类的定义,演示使用Point类的对象. #define _SCL_SECURE_NO_WARNINGS #include <ios ...
- C++_基础_类和对象
内容: (1)引用 (2)类型转换 (3)C++社区给C程序员的建议 (4)面向对象编程的概念 (5)类和对象 (6)构造函数 (7)初始化列表及其必要性 1.引用1.1 指针和引用的使用说明(1)指 ...
- Java精选笔记_面向对象(慨念、类和对象)
面向对象概念 在程序中使用对象来映射现实中的事物,使用对象的关系来描述事物之间的联系,这种思想就是面向对象. 相对于面向过程而言.是一种思想,强调的是功能的对象. 面向对象的本质:以类的方式组织代码, ...
- C++_类和对象
类和对象 OOP第二课 1 类的构成 1.1 从结构到类 1.2 类的构成 2 成员函数的声明 2.1 普通成员函数形式 2.2 将成员函数以内联函数的形式进行说明 3 对象的定义和使用 3.1 对象 ...
随机推荐
- 查看tablespace的使用情况
by tablespace(使用单位G): SELECT a.tablespace_name,(all_size-b.unuse_size) use_size,b.unuse_size,a.all_s ...
- Microsoft SQL Server,错误:2;SQL Server配置管理器(本地)—远程过程调用失败
本机是先安装sqlserver2008,后安装vs2012 在安装sqlserver2008后,运行sqlserver2008正常,接着安装vs2012,再运行sqlserver2008,问题出现了, ...
- ESB、SOA、EAI异同【转】
先说概念: ESB:企业服务总线(ESB : Enterprise Service Bus):ESB 是一种开放的.基于标准的分布式同步或异步信息传递中间件.通过 XML.Web Serv ...
- tomcat 服务器全解
①B/S.C/S比较 ⑴C/S C/S结构即客户端/服务器(Client/Server),例如QQ: 需要编写服务器端程序,以及客户端程序,例如我们安装的就是QQ的客户端程序: 缺点:软件更新时需要同 ...
- 如何进行Hadoop二次开发指导视频下载
本视频适合对Java有一定了解,熟悉java se的Hadoop爱好者,想对Hadoop进行二次开发.下面是以伪分布为例: 想对Hadoop二次开发:一.首先需要Hadoop和Java之间搭建Ecli ...
- c c++ 函数入口和出口的hook(gcc 编译选项),然后打印出函数调用关系的方法
GCC Function instrumentation机制可以用来跟踪函数的调用关系,在gcc中对应的选项为“-finstrument-functions”.可查看gcc的man page来获取更详 ...
- BCP的用法
bcp kaiser..kp_rates in c:\kp.bcp -U buykporg -P buykporg -S localhost -c bcp ccrm_oem_shqc.."s ...
- HDU5407.CRB and Candies(数论)
官方题解: The problem is just to calculate g(N) = LCM(C(N,0),C(N,1),...,C(N,N)) Introducing function f(n ...
- Java 网络编程最佳实践(转载)
http://yihongwei.com/2015/09/remoting-practice/ Java 网络编程最佳实践 Sep 10, 2015 | [Java, Network] 1. 通信层 ...
- jbpm4.4 demo3
package cn.itcast.c_processinstance; import java.util.List; import org.jbpm.api.Configuration; impor ...