《Java从小白到大牛》之第10章 面向对象基础(下)

《Java从小白到大牛》纸质版已经上架了!!!


Java从小白到大牛书皮

封装性与访问控制

Java面向对象的封装性是通过对成员变量和方法进行访问控制实现的,访问控制分为4个等级:私有、默认、保护和公有,具体规则如表10-1所示。

表 101 Java类成员的访问控制

可否直接访问控制等级 同一个类 同一个包 不同包的子类 不同包非子类
私有 Yes
默认 Yes Yes
保护 Yes Yes Yes
公有 Yes Yes Yes Yes

下面详细解释一下这4种访问级别。

私有级别 {#-0}

私有级别的关键字是private,私有级别的成员变量和方法只能在其所在类的内部自由使用,在其他的类中则不允许直接访问。私有级别限制性最高。私有级别示例代码如下:

// PrivateClass.java文件

package com.a51work6;

public class PrivateClass { ①

private int x; ②

public PrivateClass() { ③

x = 100;

}

private void printX() { ④

System.out.println("Value Of x is" + x);

}

}

// HelloWorld.java文件调用PrivateClass

package com.a51work6;

public class HelloWorld {

public static void main(String[] args) {

PrivateClass p;

p = new PrivateClass();

//编译错误,PrivateClass中的方法 printX()不可见

p.printX(); ⑤

}

}

上述代码第①行声明PrivateClass类,其中的代码第②行是声明私有实例变量x,代码第③行是声明公有的构造方法,构造方法将在第12章详细介绍。代码第④行声明私有实例方法。

HelloWorld类中代码第⑤行会有编译错误,因为PrivateClass中printX()的方法是私有方法。

默认级别 {#-1}

默认级别没有关键字,也就是没有访问修饰符,默认级别的成员变量和方法,可以在其所在类内部和同一个包的其他类中被直接访问,但在不同包的类中则不允许直接访问。

默认级别示例代码如下:

// DefaultClass.java文件

package com.a51work6;

public class DefaultClass {

int x; ①

public DefaultClass() {

x = 100;

}

void printX() { ②

System.out.println("Value Of x is" + x);

}

}

上述代码第①行的x变量前没有访问限制修饰符,代码第②行的方法也是没有访问限制修饰符。它们的访问级别都有默认访问级别。

在相同包(com.a51work6)中调用DefaultClass类代码如下:

// com.a51work6包中HelloWorld.java文件

package com.a51work6;

public class HelloWorld {

public static void main(String[] args) {

DefaultClass p;

p = new DefaultClass();

p.printX();

}

}

默认访问级别可以在同一包中访问,上述代码可以编译通过。

在不同的包中调用DefaultClass类代码如下:

// 默认包中HelloWorld.java文件

import com.a51work6.DefaultClass;

public class HelloWorld {

public static void main(String[] args) {

DefaultClass p;

p = new DefaultClass();

// 编译错误,DefaultClass中的方法 printX()不可见

p.printX();

}

}

该HelloWorld.java文件与DefaultClass类不在同一个包中,printX()是默认访问级别,所以p.printX()方法无法编译通过。

公有级别 {#-2}

公有级别的关键字是public,公有级别的成员变量和方法可以在任何场合被直接访问,是最宽松的一种访问控制等级。

公有级别示例代码如下:

// PublicClass.java文件

package com.a51work6;

public class PublicClass {

public int x; ①

public PublicClass() {

x = 100;

}

public void printX() { ②

System.out.println("Value Of x is" + x);

}

}

上述代码第①行的x变量是公有级别,代码第②行的方法也是公有级别。调用PublicClass类代码如下:

// 默认包中HelloWorld.java文件

import com.a51work6.PublicClass;

public class HelloWorld {

public static void main(String[] args) {

PublicClass p;

p = new PublicClass();

p.printX();

}

}

该HelloWorld.java文件与PublicClass类不在同一个包中,可以公有的printX()方法。

保护级别 {#-3}

保护级别的关键字是protected,保护级别在同一包中完全与默认访问级别一样,但是不同包中子类能够继承父类中的protected变量和方法,这就是所谓的保护级别,“保护”就是保护某个类的子类都能继承该类的变量和方法。

保护级别示例代码如下:

// ProtectedClass.java文件

package com.a51work6;

public class ProtectedClass {

protected int x; ①

public ProtectedClass() {

x = 100;

}

protected void printX() { ②

System.out.println("Value Of x is " + x);

}

}

上述代码第①行的x变量是保护级别,代码第②行的方法也是保护级别。

在相同包(com.a51work6)中调用ProtectedClass类代码如下:

// 默认包中HelloWorld.java文件

package com.a51work6;

import com.a51work6.ProtectedClass;

public class HelloWorld {

public static void main(String[] args) {

ProtectedClass p;

p = new ProtectedClass();

// 同一包中可以直接访问ProtectedClass中的方法 printX()

p.printX();

}

}

同一包中保护访问级别与默认访问级别一样,可以直接访问ProtectedClass的printX()方法,上述代码可以编译通过。

在不同的包中调用ProtectedClass类代码如下:

// 默认包中HelloWorld.java文件

import com.a51work6.ProtectedClass;

public class HelloWorld {

public static void main(String[] args) {

ProtectedClass p;

p = new ProtectedClass();

// 编译错误,不同包中不能直接访问保护方法printX()

p.printX();

}

}

该HelloWorld.java文件与ProtectedClass类不在同一个包中,不同包中不能直接访问保护方法printX(),所以p.printX()方法无法编译通过。

在不同的包中继承ProtectedClass类代码如下:

// 默认包中SubClass.java文件

import com.a51work6.ProtectedClass;

public class SubClass extends ProtectedClass {

void display() {

//printX()方法是从父类继承过来

printX(); ①

//x实例变量是从父类继承过来

System.out.println(x); ②

}

}

不同包中SubClass从ProtectedClass类继承了printX()方法和x实例变量。代码第①行是调用从父类继承下来的方法,代码第②行是调用从父类继承下来的实例变量。

提示 访问成员有两种方式:一种是调用,即通过类或对象调用它的成员,如p.printX()语句;另一种是继承,即子类继承父类的成员变量和方法。

  • 公有访问级别任何情况下两种方式都可以;
  • 默认访问级别在同一包中两种访问方式都可以,不能在包之外访问;
  • 保护访问级别在同一包中与默认访问级别一样,两种访问方式都可以。但是在不同包之外只能继承访问;
  • 私有访问级别只能在本类中通过调用方法访问,不能继承访问。

提示 访问类成员时,在能满足使用的前提下,应尽量限制类中成员的可见性,访问级别顺序是:私有级别→默认级别→保护级别→公有级别。

静态变量和静态方法

有一个Account(银行账户)类,假设它有三个成员变量:amount(账户金额)、interestRate(利率)和owner(账户名)。在这三个成员变量中,amount和owner会因人而异,对于不同的账户这些内容是不同的,而所有账户的interestRate都是相同的。

amount和owner成员变量与账户个体有关,称为“实例变量”,interestRate成员变量与个体无关,或者说是所有账户个体共享的,这种变量称为“静态变量”或“类变量”。

静态变量和静态方法示例代码如下:

// Account.java文件

package com.a51work6;

public class Account {

// 实例变量账户金额

double amount = 0.0; ①

// 实例变量账户名

String owner; ②

// 静态变量利率

static double interestRate = 0.0668; ③

// 静态方法

public static double interestBy(double amt) { ④

//静态方法可以访问静态变量和其他静态方法

return interestRate * amt; ⑤

}

// 实例方法

public String messageWith(double amt) { ⑥

//实例方法可以访问实例变量、实例方法、静态变量和静态方法

double interest = Account.interestBy(amt); ⑦

StringBuilder sb = new StringBuilder();

// 拼接字符串

sb.append(owner).append("的利息是").append(interest);

// 返回字符串

return sb.toString();

}

}

static修饰的成员变量是静态变量,见代码第③行。staitc修饰的方法是静态方法,见代码第④行。相反,没有static修饰的成员变量是实例变量,见代码第①行和第②行;没有staitc修饰的方法是实例方法,见代码第⑥行。

注意 静态方法可以访问静态变量和其他静态方法,例如访问代码第⑤行中的interestRate静态变量。实例方法可以访问实例变量、其他实例方法、静态变量和静态方法,例如访问代码第⑦行interestBy静态方法。

调用Account代码如下:

// HelloWorld.java文件

package com.a51work6;

public class HelloWorld {

public static void main(String[] args) {

// 访问静态变量

System.out.println(Account.interestRate); ①

// 访问静态方法

System.out.println(Account.interestBy(1000)); ②

Account myAccount = new Account();

// 访问实例变量

myAccount.amount = 1000000; ③

myAccount.owner = "Tony"; ④

// 访问实例方法

System.out.println(myAccount.messageWith(1000)); ⑤

// 通过实例访问静态变量

System.out.println(myAccount.interestRate); ⑥

}

}

调用静态变量或静态方法时,可以通过类名或实例名调用,代码第①行Account.interestRate通过类名调用静态变量,代码第②行Account.interestBy(1000)是通过类名调用静态方法。代码第⑥行是通过实例调用静态变量。

静态代码块

前面介绍的静态变量interestRate,可以在声明同时初始化,如下代码所示。

public class Account {

// 静态变量利率

static double interestRate = 0.0668;

...

}

如果初始化静态变量不是简单常量,需要进行计算才能初始化,可以使用静态(static)代码块,静态代码块在类第一次加载时执行,并只执行一次。示例代码如下:

// Account.java文件

package com.a51work6;

public class Account {

// 实例变量账户金额

double amount = 0.0;

// 实例变量账户名

String owner;

// 静态变量利率

static double interestRate;

// 静态方法

public static double interestBy(double amt) {

// 静态方法可以访问静态变量和其他静态方法

return interestRate * amt;

}

// 静态代码块

static { ①

System.out.println("静态代码块被调用...");

// 初始化静态变量

interestRate = 0.0668; ②

}

}

上述代码第①行是静态代码块,在静态代码块中可以初始化静态变量,见代码第②行,也可以调用静态方法。

调用Account代码如下:

// HelloWorld.java文件

package com.a51work6;

public class HelloWorld {

public static void main(String[] args) {

Account myAccount = new Account(); ①

// 访问静态变量

System.out.println(Account.interestRate); ②

// 访问静态方法

System.out.println(Account.interestBy(1000));

}

}

Account静态代码块是在第一次加载Account类时调用。上述代码第①行是第一次使用Account类,此时会调用静态代码块。

本章小结

本章主要介绍了面向对象基础知识。首先介绍了面向对象一些基本概念,面向对象三个基本特性。然后介绍了类、包、方法重载和访问控制。最后介绍了静态变量、静态方法和静态代码块。

配套视频

http://www.zhijieketang.com/classroom/6/courses

配套源代码

http://www.zhijieketang.com/group/5

与本书免费版对应的还有一个收费版本:

  1. 进入百度阅读电子书

  2. 进入图灵社区电子书

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,884评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,755评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,369评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,799评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,910评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,096评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,159评论 3 411
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,917评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,360评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,673评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,814评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,509评论 4 334
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,156评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,882评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,123评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,641评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,728评论 2 351

推荐阅读更多精彩内容