提交 d1363b04 编写于 作者: 沉默王二's avatar 沉默王二 💬

封装继承,多态

上级 8b6a85f2
......@@ -132,21 +132,22 @@
- [简单过了一下Java中的包](docs/oo/package.md)
- [Java中的变量:局部变量、成员变量、静态变量、常量](docs/oo/var.md)
- [Java中的方法:实例方法、静态方法、抽象方法](docs/oo/method.md)
- [聊聊Java中的可变参数](docs/basic-extra-meal/varables.md)
- [手把手教你用 C语言实现 Java native 方法](docs/oo/native-method.md)
- [Java中的构造方法:对象创建时的必经之路](docs/oo/construct.md)
- [构造方法:Java对象创建时的必经之路](docs/oo/construct.md)
- [聊一聊Java中的访问权限修饰符](docs/oo/access-control.md)
- [Java中的代码初始化块:对成员变量进行更复杂的赋值](docs/oo/code-init.md)
- [Java中的代码初始化块](docs/oo/code-init.md)
- [Java抽象类,看这一篇就够了,豁然开朗](docs/oo/abstract.md)
- [Java接口,看这一篇就够了,简单易懂](docs/oo/interface.md)
- [Java 抽象类和接口的区别,看这一篇就够了](docs/oo/abstract-vs-interface.md)
- [Java内部类详解:成员内部类、局部内部类、匿名内部类、静态内部类](docs/oo/inner-class.md)
- [Java中this和super的用法总结](docs/oo/this-super.md)
- [Java 方法重写 Override 和方法重载 Overload 的区别,一下子就明白了](docs/basic-extra-meal/override-overload.md)
- [Java 抽象类和接口的区别](docs/oo/abstract-vs-interface.md)
- [聊聊Java内部类:成员内部类、局部内部类、匿名内部类、静态内部类](docs/oo/inner-class.md)
- [聊聊 Java 封装](docs/oo/encapsulation.md)
- [深入理解 Java 继承](docs/oo/extends-bigsai.md)
- [聊聊 Java 多态](docs/oo/polymorphism.md)
- [Java中this和super关键字的用法总结](docs/oo/this-super.md)
- [一文彻底搞懂 Java static 关键字:静态变量、静态方法、静态代码块、静态内部类](docs/oo/static.md)
- [一文彻底搞懂 Java final 关键字](docs/oo/final.md)
- [这次彻底搞清楚了 Java 的三大特征之一:封装](docs/oo/encapsulation.md)
- [一万字彻底搞懂 Java 继承(三大特征之一)](docs/oo/extends-bigsai.md)
- [几句话,直观解释清楚 Java 多态(三大特征之一)](docs/oo/polymorphism.md)
- [Java 方法重写 Override 和方法重载 Overload 的区别,一下子就明白了](docs/basic-extra-meal/override-overload.md)
## 集合框架(容器)
......@@ -212,11 +213,9 @@
- [Java到底是值传递还是引用传递?](docs/basic-extra-meal/pass-by-value.md)
- [详解Java中Comparable和Comparator接口的区别](docs/basic-extra-meal/comparable-omparator.md)
- [为什么JDK源码中,无限循环大多使用for(;;)而不是while(true)?](docs/basic-extra-meal/jdk-while-for-wuxian-xunhuan.md)
- [Java 中,先有Class还是先有Object?](docs/basic-extra-meal/class-object.md)
- [详解Java中instanceof关键字的用法](docs/basic-extra-meal/instanceof.md)
- [instanceof关键字是如何实现的?](docs/basic-extra-meal/instanceof-jvm.md)
- [深入理解Java中的不可变对象](docs/basic-extra-meal/immutable.md)
- [Java中可变参数的使用](docs/basic-extra-meal/varables.md)
- [深入理解Java中的泛型](docs/basic-extra-meal/generic.md)
- [Java不能实现真正泛型的原因是什么?](docs/basic-extra-meal/true-generic.md)
- [深入理解Java中的注解](docs/basic-extra-meal/annotation.md)
......
......@@ -145,6 +145,8 @@ export const sidebarConfig = sidebar({
"oo/package",
"oo/var",
"oo/method",
"basic-extra-meal/varables",
"oo/native-method",
"oo/construct",
"oo/access-control",
"oo/code-init",
......@@ -152,14 +154,13 @@ export const sidebarConfig = sidebar({
"oo/interface",
"oo/abstract-vs-interface",
"oo/inner-class",
"oo/encapsulation",
"oo/extends-bigsai",
"oo/polymorphism",
"oo/this-super",
"basic-extra-meal/override-overload",
"oo/static",
"oo/final",
"oo/encapsulation",
"oo/extends-bigsai",
"oo/polymorphism",
],
},
{
......@@ -247,11 +248,9 @@ export const sidebarConfig = sidebar({
"pass-by-value",
"comparable-omparator",
"jdk-while-for-wuxian-xunhuan",
"class-object",
"instanceof",
"instanceof-jvm",
"immutable",
"varables",
"generic",
"true-generic",
"annotation",
......
---
title: 详解Java中可变参数的使用
shortTitle: 详解Java中可变参数的使用
title: 聊聊Java中的可变参数
shortTitle: Java中的可变参数
category:
- Java核心
tag:
......@@ -9,12 +9,12 @@ description: Java程序员进阶之路,小白的零基础Java教程,从入
head:
- - meta
- name: keywords
content: Java,Java SE,Java基础,Java教程,Java程序员进阶之路,Java入门,教程,java,可变参数
content: Java,Java SE,Java基础,Java教程,Java程序员进阶之路,Java入门,教程,java,可变参数,java 可变参数
---
# 详解Java中可变参数的使用
# 5.5 Java中的可变参数
为了让铁粉们能白票到阿里云的服务器,老王当了整整两天的客服,真正体验到了什么叫做“为人民群众谋福利”的不易和辛酸。正在他眼睛红肿打算要休息之际,小二跑过来问他:“Java 的可变参数究竟是怎么一回事?”老王一下子又清醒了,他爱 Java,他爱传道解惑,他爱这群尊敬他的读者
为了让铁粉们能白票到阿里云的服务器,我当了整整两天的客服,真正体验到了什么叫做“为人民群众谋福利”的不易和辛酸。正在我眼睛红肿打算要休息之际,三妹跑过来问:“Java 的可变参数究竟是怎么一回事?”我一下子又清醒了,我爱 Java,我爱传道解惑,也享受三妹的赞许(😂)
可变参数是 Java 1.5 的时候引入的功能,它允许方法使用任意多个、类型相同(`is-a`)的值作为参数。就像下面这样。
......@@ -43,10 +43,7 @@ public static void print(String... strs) {
![](https://cdn.tobebetterjavaer.com/tobebetterjavaer/images/basic-extra-meal/varables-02.png)
可变参数看起来就像是个语法糖,它背后究竟隐藏了什么呢?老王想要一探究竟,它在追求真理这条路上一直很执着。
可变参数看起来就像是个语法糖,它背后究竟隐藏了什么呢?让我们来一探究竟,在追求真理这条路上我们要执着。
其实也很简单。**当使用可变参数的时候,实际上是先创建了一个数组,该数组的大小就是可变参数的个数,然后将参数放入数组当中,再将数组传递给被调用的方法**
......@@ -69,11 +66,7 @@ public static void print(String... strs) {
那如果方法的参数是一个数组,然后像使用可变参数那样去调用方法的时候,能行得通吗?
*留个思考题,大家也可以去试一试*
那一般什么时候使用可变参数呢?
“三妹,给你留个思考题:一般什么时候使用可变参数呢?”
可变参数,可变参数,顾名思义,当一个方法需要处理任意多个相同类型的对象时,就可以定义可变参数。Java 中有一个很好的例子,就是 String 类的 `format()` 方法,就像下面这样。
......@@ -86,7 +79,7 @@ System.out.println(String.format("年纪是: %d 名字是: %s", 18, "沉默王
如果不使用可变参数,那需要格式化的参数就必须使用“+”号操作符拼接起来了。麻烦也就惹上身了。
在实际的项目代码中,开源包 slf4j.jar 的日志输出就经常要用到可变参数(log4j 就没法使用可变参数,日志中需要记录多个参数时就痛苦不堪了)。就像下面这样。
在实际的项目代码中,[slf4j](https://tobebetterjavaer.com/gongju/slf4j.html) 的日志输出就经常要用到可变参数([log4j](https://tobebetterjavaer.com/gongju/log4j.html) 就没法使用可变参数,日志中需要记录多个参数时就痛苦不堪了)。就像下面这样。
```java
protected Logger logger = LoggerFactory.getLogger(getClass());
......@@ -100,7 +93,7 @@ logger.debug("名字是{},年纪是{}", mem.getName(), mem.getAge());
public void debug(String format, Object... arguments);
```
那在使用可变参数的时候有什么注意事项吗?
“那在使用可变参数的时候有什么注意事项吗?”三妹问。
有的。我们要避免重载带有可变参数的方法——这样很容易让编译器陷入自我怀疑中。
......@@ -126,7 +119,6 @@ public static void print(Integer... ints) {
![](https://cdn.tobebetterjavaer.com/tobebetterjavaer/images/basic-extra-meal/varables-03.png)
假如真的需要重载带有可变参数的方法,就必须在调用方法的时候给出明确的指示,不要让编译器去猜。
```java
......@@ -147,6 +139,10 @@ public static void print(Integer... ints) {
上面这段代码是可以编译通过的。因为编译器知道参数是 String 类型还是 Integer 类型,只不过为了运行时不抛出 `NullPointerException`,两个 `print()` 方法的内部要做好判空操作。
“好了,关于可变参数,我们就先讲到这里吧。三妹,你都理解了吧?”
“嗯嗯,不难,我理解了,哥。”三妹最近的学习状态真不错,能看得出来,她有在认真地做笔记📒。
---
......
......@@ -143,21 +143,22 @@ head:
- [简单过了一下Java中的包](oo/package.md)
- [Java中的变量:局部变量、成员变量、静态变量、常量](oo/var.md)
- [Java中的方法:实例方法、静态方法、抽象方法](oo/method.md)
- [聊聊Java中的可变参数](basic-extra-meal/varables.md)
- [手把手教你用 C语言实现 Java native 方法](oo/native-method.md)
- [Java中的构造方法:对象创建时的必经之路](oo/construct.md)
- [构造方法:Java对象创建时的必经之路](oo/construct.md)
- [聊一聊Java中的访问权限修饰符](oo/access-control.md)
- [Java中的代码初始化块:对成员变量进行更复杂的赋值](oo/code-init.md)
- [Java中的代码初始化块](oo/code-init.md)
- [Java抽象类,看这一篇就够了,豁然开朗](oo/abstract.md)
- [Java接口,看这一篇就够了,简单易懂](oo/interface.md)
- [Java 抽象类和接口的区别,看这一篇就够了](oo/abstract-vs-interface.md)
- [Java内部类详解:成员内部类、局部内部类、匿名内部类、静态内部类](oo/inner-class.md)
- [Java中this和super的用法总结](oo/this-super.md)
- [Java 方法重写 Override 和方法重载 Overload 的区别,一下子就明白了](basic-extra-meal/override-overload.md)
- [Java 抽象类和接口的区别](oo/abstract-vs-interface.md)
- [聊聊Java内部类:成员内部类、局部内部类、匿名内部类、静态内部类](oo/inner-class.md)
- [聊聊 Java 封装](oo/encapsulation.md)
- [深入理解 Java 继承](oo/extends-bigsai.md)
- [聊聊 Java 多态](oo/polymorphism.md)
- [Java中this和super关键字的用法总结](oo/this-super.md)
- [一文彻底搞懂 Java static 关键字:静态变量、静态方法、静态代码块、静态内部类](oo/static.md)
- [一文彻底搞懂 Java final 关键字](oo/final.md)
- [这次彻底搞清楚了 Java 的三大特征之一:封装](oo/encapsulation.md)
- [一万字彻底搞懂 Java 继承(三大特征之一)](oo/extends-bigsai.md)
- [几句话,直观解释清楚 Java 多态(三大特征之一)](oo/polymorphism.md)
- [Java 方法重写 Override 和方法重载 Overload 的区别,一下子就明白了](basic-extra-meal/override-overload.md)
### 集合框架(容器)
......@@ -223,7 +224,6 @@ head:
- [Java到底是值传递还是引用传递?](basic-extra-meal/pass-by-value.md)
- [详解Java中Comparable和Comparator接口的区别](basic-extra-meal/comparable-omparator.md)
- [为什么JDK源码中,无限循环大多使用for(;;)而不是while(true)?](basic-extra-meal/jdk-while-for-wuxian-xunhuan.md)
- [Java 中,先有Class还是先有Object?](basic-extra-meal/class-object.md)
- [详解Java中instanceof关键字的用法](basic-extra-meal/instanceof.md)
- [instanceof关键字是如何实现的?](basic-extra-meal/instanceof-jvm.md)
- [深入理解Java中的不可变对象](basic-extra-meal/immutable.md)
......
---
title: Java 抽象类和接口的区别,看这一篇就够了
shortTitle: Java抽象类和接口的区别
shortTitle: 抽象类和接口的区别
description: Java程序员进阶之路,小白的零基础Java教程,认真聊聊 Java抽象类和接口的区别
category:
- Java 核心
......@@ -9,16 +9,21 @@ tag:
head:
- - meta
- name: keywords
content: Java,Java SE,Java基础,Java教程,Java程序员进阶之路,Java入门,教程,Java 接口,接口,interface
content: Java,Java SE,Java基础,Java教程,Java程序员进阶之路,Java入门,教程,java 抽象类 接口,java interface abstract
---
通过前面两篇,我们已经深入地了解了 Java 抽象类和 Java 接口,那这篇我们来重点说一下抽象类和接口之间的区别。
# 5.12 抽象类和接口的区别
## 01、抽象类
“三妹,通过前面两篇,我们已经深入地了解了 Java [抽象类](https://tobebetterjavaer.com/oo/abstract.html)和 Java [接口](https://tobebetterjavaer.com/oo/interface.html),那这篇我们来重点说一下抽象类和接口之间的区别。”我放下手中的鼠标和键盘,转向右手边,对三妹说。
“好啊。我挺想总结一波的,也算是对抽象类和接口做个了结。”三妹回应到。
### 01、抽象类
在 Java 中,通过关键字 `abstract` 定义的类叫做抽象类。Java 是一门面向对象的语言,因此所有的对象都是通过类来描述的;但反过来,并不是所有的类都是用来描述对象的,抽象类就是其中的一种。
以下示例展示了一个简单的抽象类:
```java
// 个人认为,一名教练必须攻守兼备
abstract class Coach {
......@@ -28,15 +33,15 @@ abstract class Coach {
}
```
## 02、接口
### 02、接口
我们知道,有抽象方法的类被称为抽象类,也就意味着抽象类中还能有不是抽象方法的方法。这样的类就不能算作纯粹的接口,尽管它也可以提供接口的功能——只能说抽象类是普通类与接口之间的一种中庸之道。
**接口(英文:Interface),在 Java 中是一个抽象类型,是抽象方法的集合**;接口通过关键字 `interface` 来定义。接口与抽象类的不同之处在于:
1、抽象类可以有方法体的方法,但接口没有
2、接口中的成员变量隐式为 `static final`,但抽象类不是的。
3、一个类可以实现多个接口,但只能继承一个抽象类。
- 1、抽象类可以有方法体的方法,但接口没有(Java 8 以前)
- 2、接口中的成员变量隐式为 `static final`,但抽象类不是的。
- 3、一个类可以实现多个接口,但只能继承一个抽象类。
以下示例展示了一个简单的接口:
......@@ -53,21 +58,20 @@ interface Coach {
- 接口的每个方法都是隐式抽象的,所以同样不需要使用 `abstract` 关键字;
- 接口中的方法都是隐式 `public` 的。
## 03、两者差别
### 03、两者差别
“哦,我理解了哥。那我再问一下,抽象类和接口有什么差别呢?”
“哇,三妹呀,你这个问题恰到好处,问到了点子上。”我不由得为三妹竖起了大拇指。
1)语法层面上
#### 1)语法层面上
- 抽象类可以提供成员方法的实现细节,而接口中只能存在public abstract 方法;
- 抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是public static final类型的;
- 接口中不能含有静态代码块,而抽象类可以有静态代码块;
- 一个类只能继承一个抽象类,而一个类却可以实现多个接口。
2)设计层面上
#### 2)设计层面上
抽象类是对一种事物的抽象,即对类抽象,继承抽象类的子类和抽象类本身是一种 `is-a` 的关系。而接口是对行为的抽象。抽象类是对整个类整体进行抽象,包括属性、行为,但是接口却是对类局部(行为)进行抽象。
......
......@@ -12,16 +12,15 @@ head:
content: Java,Java SE,Java基础,Java教程,Java程序员进阶之路,Java入门,教程,Java抽象类,抽象类
---
# 5.10 Java抽象类
“二哥,你这明显加快了更新的频率呀!”三妹对于我最近的肝劲由衷的佩服了起来。
“哈哈,是呀,我要给广大的学弟学妹们一个完整的 Java 学习体系。”我对未来充满了信心。
“哈哈,是呀,我要给广大的学弟学妹们一个完整的 Java 学习体系,记住我们的口号,**学 Java 就上二哥的 Java 进阶之路**。”我对未来充满了信心。
“那就开始吧。”三妹说。
---
## 定义抽象类
### 01、定义抽象类
定义抽象类的时候需要用到关键字 `abstract`,放在 `class` 关键字前,就像下面这样。
......@@ -30,9 +29,9 @@ abstract class AbstractPlayer {
}
```
关于抽象类的命名,《阿里的 Java 开发手册》上有强调,“抽象类命名要使用 Abstract 或 Base 开头”,这条规约还是值得遵守的
关于抽象类的命名,《[阿里的 Java 开发手册](https://tobebetterjavaer.com/pdf/ali-java-shouce.html)》上有强调,“抽象类命名要使用 Abstract 或 Base 开头”,这条规约还是值得遵守的,真正做到名如其意
## 抽象类的特征
### 02、抽象类的特征
抽象类是不能实例化的,尝试通过 `new` 关键字实例化的话,编译器会报错,提示“类是抽象的,不能实例化”。
......@@ -82,13 +81,13 @@ public class BasketballPlayer extends AbstractPlayer {
![](https://cdn.tobebetterjavaer.com/tobebetterjavaer/images/object-class/abstract-04.png)
## 抽象类的应用场景
### 03、抽象类的应用场景
“二哥,抽象方法我明白了,那什么时候使用抽象方法呢?能给我讲讲它的应用场景吗?”三妹及时的插话道。
“这问题问的恰到好处呀!”我扶了扶眼镜继续说。
### **第一种场景**
#### **01)第一种场景**
当我们希望一些通用的功能被多个子类复用的时候,就可以使用抽象类。比如说,AbstractPlayer 抽象类中有一个普通的方法 `sleep()`,表明所有运动员都需要休息,那么这个方法就可以被子类复用。
......@@ -130,7 +129,7 @@ footballPlayer.sleep();
这样是不是就实现了代码的复用呢?
### **第二种场景**
#### **02)第二种场景**
当我们需要在抽象类中定义好 API,然后在子类中扩展实现的时候就可以使用抽象类。比如说,AbstractPlayer 抽象类中定义了一个抽象方法 `play()`,表明所有运动员都可以从事某项运动,但需要对应子类去扩展实现,表明篮球运动员打篮球,足球运动员踢足球。
......@@ -162,23 +161,45 @@ public class FootballPlayer extends AbstractPlayer {
}
```
为了进一步展示抽象类的特性,我们再来看一个具体的示例。假设现在有一个文件,里面的内容非常简单,只有一个“Hello World”,现在需要有一个读取器将内容从文件中读取出来,最好能按照大写的方式,或者小写的方式来读。
为了进一步展示抽象类的特性,我们再来看一个具体的示例。
>PS:[网站](https://tobebetterjavaer.com/oo/abstract.html)评论区说涉及到了文件的读写以及 Java 8 的新特性,不适合新人,如果觉得自己实在是看不懂,跳过,等学了 IO 流再来看也行。如果说是为了复习 Java 基础知识,就不存在这个问题了。
假设现在有一个文件,里面的内容非常简单,只有一个“Hello World”,现在需要有一个读取器将内容从文件中读取出来,最好能按照大写的方式,或者小写的方式来读。
这时候,最好定义一个抽象类 BaseFileReader:
```java
/**
* 抽象类,定义了一个读取文件的基础框架,其中 mapFileLine 是一个抽象方法,具体实现需要由子类来完成
*/
abstract class BaseFileReader {
protected Path filePath;
protected Path filePath; // 定义一个 protected 的 Path 对象,表示读取的文件路径
/**
* 构造方法,传入读取的文件路径
* @param filePath 读取的文件路径
*/
protected BaseFileReader(Path filePath) {
this.filePath = filePath;
}
/**
* 读取文件的方法,返回一个字符串列表
* @return 字符串列表,表示文件的内容
* @throws IOException 如果文件读取出错,抛出该异常
*/
public List<String> readFile() throws IOException {
return Files.lines(filePath)
.map(this::mapFileLine).collect(Collectors.toList());
return Files.lines(filePath) // 使用 Files 类的 lines 方法,读取文件的每一行
.map(this::mapFileLine) // 对每一行应用 mapFileLine 方法,将其转化为指定的格式
.collect(Collectors.toList()); // 将处理后的每一行收集到一个字符串列表中,返回
}
/**
* 抽象方法,子类需要实现该方法,将文件中的每一行转化为指定的格式
* @param line 文件中的每一行
* @return 转化后的字符串
*/
protected abstract String mapFileLine(String line);
}
```
......@@ -250,14 +271,14 @@ public class FileReaderTest {
[HELLO WORLD]
```
## 抽象类总结
### 04、抽象类总结
好了,对于抽象类我们简单总结一下:
1、抽象类不能被实例化。
2、抽象类应该至少有一个抽象方法,否则它没有任何意义。
3、抽象类中的抽象方法没有方法体。
4、抽象类的子类必须给出父类中的抽象方法的具体实现,除非该子类也是抽象类。
- 1、抽象类不能被实例化。
- 2、抽象类应该至少有一个抽象方法,否则它没有任何意义。
- 3、抽象类中的抽象方法没有方法体。
- 4、抽象类的子类必须给出父类中的抽象方法的具体实现,除非该子类也是抽象类。
“完了吗?二哥”三妹似乎还沉浸在聆听教诲的快乐中。
......
---
title: 聊一聊Java中的访问权限修饰符
shortTitle: 聊一聊Java中的访问权限修饰符
shortTitle: Java中的访问权限修饰符
description: Java程序员进阶之路,小白的零基础Java教程,聊一聊Java中的访问权限修饰符
category:
- Java 核心
......@@ -12,8 +12,13 @@ head:
content: Java,Java SE,Java基础,Java教程,Java程序员进阶之路,Java入门,教程,Java访问权限修饰符,public,private,protected,访问权限修饰符
---
# 5.8 Java中的访问权限修饰符
我们先来讨论一下为什么需要访问权限控制。考虑两个场景:
“我们先来讨论一下为什么需要访问权限控制。其实之前我们在讲类和对象的时候有提到,今天我们来详细地聊一聊,三妹。”我开门见山地说,“三妹,你打开思维导图,记得做笔记哦。”
“好的。”三妹应声回答。
考虑两个场景:
场景 1:工程师 A 编写了一个类 ClassA,但是工程师 A 并不希望 ClassA 被其他类都访问到,该如何处理呢?
......@@ -30,20 +35,19 @@ head:
类只可以用默认访问权限和 public 修饰。比如说:
```
```java
public class Wanger{}
```
或者
```
```java
class Wanger{}
```
但变量和方法则都可以修饰。
## 1. 修饰类
### 1. 修饰类
- 默认访问权限(包访问权限):用来修饰类的话,表示该类只对同一个包中的其他类可见。
- public:用来修饰类的话,表示该类对其他所有的类都可见。
......@@ -53,7 +57,7 @@ class Wanger{}
Main.java:
```
```java
package com.tobetterjavaer.test1;
public class Main {
......@@ -68,7 +72,7 @@ public class Main {
People.java
```
```java
package com.tobetterjavaer.test1;
class People {//默认访问权限(包访问权限)
......@@ -95,7 +99,7 @@ class People {//默认访问权限(包访问权限)
People.java
```
```java
package com.tobetterjavaer.test2;
class People {//默认访问权限(包访问权限)
......@@ -128,7 +132,7 @@ class People {//默认访问权限(包访问权限)
正如上图的快速修正提示所示,将 People 类的默认访问权限更改为 public 的话,People 类对于 Main 类便可见了。
## 2. 修饰类的方法和变量
### 2. 修饰方法和变量
- 默认访问权限(包访问权限):如果一个类的方法或变量被包访问权限修饰,也就意味着只能在同一个包中的其他类中显示地调用该类的方法或者变量,在不同包中的类中不能显式地调用该类的方法或变量。
- private:如果一个类的方法或者变量被 private 修饰,那么这个类的方法或者变量只能在该类本身中被访问,在类外以及其他类中都不能显式的进行访问。
......@@ -142,7 +146,7 @@ Main.java 没有变化
People.java
```
```java
package com.tobebetterjavaer.test1;
public class People {
......@@ -167,7 +171,7 @@ public class People {
但是如果 People 类和 Main 类不在同一个包中:
```
```java
package com.tobebetterjavaer.test2; //与Main类处于不同包中
public class People {
......@@ -200,7 +204,7 @@ public class People {
People.java
```
```java
package com.tobebetterjavaer.test1;
public class People {
......@@ -225,7 +229,7 @@ public class People {
如果 People 类和 Main 类处于不同包中:
```
```java
package com.tobebetterjavaer.test2;
public class People {
......@@ -254,7 +258,7 @@ public class People {
如果在 com.cxh.test1 中定一个类 Man 继承 People,则可以在类 Man 中显示调用方法 getName 和 setName:
```
```java
package com.tobebetterjavaer.test1;
import com.tobebetterjavaer.test2.People;
......@@ -279,11 +283,15 @@ public class Man extends People {
另外,如果还存在其他类,这些类在包外是不可见的。如果源代码文件没有 public 类,则源代码文件的名称可以随意命名。
>原文链接:[https://www.cnblogs.com/dolphin0520/p/3734915.html](https://www.cnblogs.com/dolphin0520/p/3734915.html) 作者: Matrix海子,编辑:沉默王二
“三妹,理解了吧?”我问三妹。
“是的,很简单,换句话说,不想让别人看的就 private,想让人看的就 public,想同一个班级/部门看的就默认,想让下一级看的就 protected,对吧?哥”三妹很自信地回答。
----
“不错不错,总结得有那味了。”
>原文链接:[https://www.cnblogs.com/dolphin0520/p/3734915.html](https://www.cnblogs.com/dolphin0520/p/3734915.html) 作者: Matrix海子,编辑:沉默王二
----
最近整理了一份牛逼的学习资料,包括但不限于Java基础部分(JVM、Java集合框架、多线程),还囊括了 **数据库、计算机网络、算法与数据结构、设计模式、框架类Spring、Netty、微服务(Dubbo,消息队列) 网关** 等等等等……详情戳:[可以说是2022年全网最全的学习和找工作的PDF资源了](https://tobebetterjavaer.com/pdf/programmer-111.html)
......
---
title: Java中的代码初始化块:对成员变量进行更复杂的赋值
title: Java中的代码初始化块
shortTitle: Java中的代码初始化块
description: Java程序员进阶之路,小白的零基础Java教程,认真聊聊 Java中的代码初始化块:对成员变量进行更复杂的赋值
category:
......@@ -12,6 +12,7 @@ head:
content: Java,Java SE,Java基础,Java教程,Java程序员进阶之路,Java入门,教程,Java代码初始化块,代码初始化块
---
# 5.9 Java中的代码初始化块
“哥,今天我们要学习的内容是‘代码初始化块’,对吧?”看来三妹已经提前预习了我上次留给她的作业。
......@@ -86,7 +87,7 @@ public class Car {
![](https://cdn.tobebetterjavaer.com/tobebetterjavaer/images/object-class/22-01.png)
“哦,原来如此啊!”三妹仿佛发现了新大陆,意味深长地说
“哦,原来如此啊!”三妹仿佛发现了新大陆,意味深长地说,“编译器把代码初始化块放到了构造方法中,怪不得。”
等三妹明白彻底搞明白后,我对她继续说道:“对于代码初始化来说,它有三个规则。”
......@@ -129,8 +130,9 @@ public class B extends A{
“这个例子再次印证了之前的第二条规则:代码初始化块是放在构造方法中执行的,只不过比较靠前。”
----
“好了,今天就先讲到这吧,中午休息一下,下午的精神会更足。”刚对三妹说完这句话,我的哈欠就上来了,好困。
----
最近整理了一份牛逼的学习资料,包括但不限于Java基础部分(JVM、Java集合框架、多线程),还囊括了 **数据库、计算机网络、算法与数据结构、设计模式、框架类Spring、Netty、微服务(Dubbo,消息队列) 网关** 等等等等……详情戳:[可以说是2022年全网最全的学习和找工作的PDF资源了](https://tobebetterjavaer.com/pdf/programmer-111.html)
......
---
title: Java中的构造方法:对象创建时的必经之路
shortTitle: Java 中的构造方法
title: 构造方法:Java对象创建时的必经之路
shortTitle: Java中的构造方法
description: Java程序员进阶之路,小白的零基础Java教程,认真聊聊 Java中的构造方法:对象创建时的必经之路
category:
- Java 核心
......@@ -9,31 +9,34 @@ tag:
head:
- - meta
- name: keywords
content: Java,Java SE,Java基础,Java教程,Java程序员进阶之路,Java入门,教程,Java构造方法,构造方法
content: Java,Java SE,Java基础,Java教程,Java程序员进阶之路,Java入门,教程,Java构造方法,构造方法,java construct
---
# 5.7 Java中的构造方法
我对三妹说,“上一节学了 Java 中的方法,接着学构造方法的话,难度就小很多了。”
“三妹,[上一节](https://tobebetterjavaer.com/oo/method.html)学了 Java 中的方法,接着学构造方法的话,难度就小很多了。”刚吃完中午饭,虽然有些困意,但趁机学个 10 分钟也是不错的,睡眠会更心满意足一些,于是我面露微笑地对三妹说。
“在 Java 中,构造方法是一种特殊的方法,当一个类被实例化的时候,就会调用构造方法。只有在构造方法被调用的时候,对象才会被分配内存空间。每次使用 `new` 关键字创建对象的时候,构造方法至少会被调用一次。”
“如果你在一个类中没有看见构造方法,并不是因为构造方法不存在,而是被缺省了,编译器会给这个类提供一个默认的构造方法。往大的方面说,就是,Java 有两种类型的构造方法:**无参构造方法和有参构造方法**。”
“如果你在一个类中没有看见构造方法,并不是因为构造方法不存在,而是被缺省了,编译器会给这个类提供一个默认的构造方法。就是说,Java 有两种类型的构造方法:**无参构造方法和有参构造方法**。”
“注意,之所以叫它构造方法,是因为对象在创建的时候,需要通过构造方法初始化值——就是描写对象的那些状态,对应的是类中的字段。”
“注意,之所以叫它构造方法,是因为对象在创建的时候,需要通过构造方法初始化值——描写对象有哪些初始化状态。”
## 01、创建构造方法的规则有哪些
“哥,你缓缓,一口气说这么多,也真有你的。”三妹听得聚精会神,但也知道关心她这个既当哥又当老师的二哥了。
### 01、创建构造方法的规则
构造方法必须符合以下规则:
- 构造方法的名字必须和类名一样;
- 构造方法没有返回类型,包括 void;
- 构造方法不能是抽象的、静态的、最终的、同步的,也就是说,构造方法不能通过 abstract、static、final、synchronized 关键字修饰
- 构造方法不能是抽象的(abstract)、静态的(static)、最终的(final)、同步的(synchronized)
简单解析一下最后一条规则。
- 由于构造方法不能被子类继承,所以用 final 和 abstract 修饰没有意义;
- 构造方法用于初始化一个对象,所以用 static 修饰没有意义;
- 多个线程不会同时创建内存地址相同的同一个对象,所以用 synchronized 修饰没有必要。
- 由于构造方法不能被子类继承,所以用 final 和 abstract 关键字修饰没有意义;
- 构造方法用于初始化一个对象,所以用 static 关键字修饰没有意义;
- 多个线程不会同时创建内存地址相同的同一个对象,所以用 synchronized 关键字修饰没有必要。
构造方法的语法格式如下:
......@@ -74,10 +77,10 @@ public class Demo {
`public Demo() {}` 才是真正的无参构造方法。
不过,可以使用访问权限修饰符(private、protected、public、default)来修饰构造方法,访问权限修饰符决定了构造方法的创建方式。
不过,可以使用[访问权限修饰符](https://tobebetterjavaer.com/oo/access-control.html)(private、protected、public、default)来修饰构造方法,访问权限修饰符决定了构造方法的创建方式。
## 02、什么是默认构造方法
### 02、默认构造方法
如果一个构造方法中没有任何参数,那么它就是一个默认构造方法,也称为无参构造方法。
......@@ -104,7 +107,7 @@ public class Bike {
一辆自行车被创建
```
通常情况下,无参构造方法是可以缺省的,我们开发者并不需要显式的声明无参构造方法,把这项工作交给编译器更轻松一些
通常情况下,无参构造方法是可以缺省的,我们开发者并不需要显式的声明无参构造方法,把这项工作交给编译器就可以了
![](https://cdn.tobebetterjavaer.com/tobebetterjavaer/images/object-class/18-01.png)
......@@ -136,7 +139,7 @@ public class Person {
在上面的例子中,默认构造方法初始化了 name 和 age 的值,name 是 String 类型,所以默认值为 null,age 是 int 类型,所以默认值为 0。如果没有默认构造方法的话,这项工作就无法完成了。
## 03、什么是有参构造方法
### 03、有参构造方法
有参数的构造方法被称为有参构造方法,参数可以有一个或多个。有参构造方法可以为不同的对象提供不同的值。当然,也可以提供相同的值。
......@@ -177,9 +180,9 @@ new ParamConstructorPerson("沉默王三",16);
如果没有有参构造方法的话,就需要通过 setter 方法给字段赋值了。
## 04、如何重载构造方法
### 04、重载构造方法
在 Java 中,构造方法和方法类似,只不过没有返回类型。它也可以像方法一样被重载。构造方法的重载也很简单,只需要提供不同的参数列表即可。编译器会通过参数的数量来决定应该调用哪一个构造方法。
在 Java 中,构造方法和方法类似,只不过没有返回类型。它也可以像方法一样被[重载](https://tobebetterjavaer.com/basic-extra-meal/override-overload.html)。构造方法的重载也很简单,只需要提供不同的参数列表即可。编译器会通过参数的数量来决定应该调用哪一个构造方法。
```java
/**
......@@ -218,7 +221,7 @@ public class OverloadingConstrutorPerson {
创建对象的时候,如果传递的是三个参数,那么就会调用 `OverloadingConstrutorPerson(String name, int age, int sex)` 这个构造方法;如果传递的是两个参数,那么就会调用 `OverloadingConstrutorPerson(String name, int age)` 这个构造方法。
## 05、构造方法和方法有什么区别
### 05、构造方法和方法的区别
构造方法和方法之间的区别还是蛮多的,比如说下面这些:
......@@ -226,7 +229,7 @@ public class OverloadingConstrutorPerson {
## 06、如何复制对象
### 06、复制对象
复制一个对象可以通过下面三种方式完成:
......@@ -234,7 +237,7 @@ public class OverloadingConstrutorPerson {
- 通过对象的值
- 通过 Object 类的 `clone()` 方法
1)通过构造方法
#### 1)通过构造方法
```java
/**
......@@ -270,7 +273,7 @@ public class CopyConstrutorPerson {
在上面的例子中,有一个参数为 CopyConstrutorPerson 的构造方法,可以把该参数的字段直接复制到新的对象中,这样的话,就可以在 new 关键字创建新对象的时候把之前的 p1 对象传递过去。
2)通过对象的值
#### 2)通过对象的值
```java
/**
......@@ -307,7 +310,7 @@ public class CopyValuePerson {
这种方式比较粗暴,直接拿 p1 的字段值复制给 p2 对象(`p2.name = p1.name`)。
3)通过 Object 类的 `clone()` 方法
#### 3)通过 Object 类的 `clone()` 方法
```java
/**
......@@ -343,7 +346,9 @@ public class ClonePerson implements Cloneable {
通过 `clone()` 方法复制对象的时候,ClonePerson 必须先实现 Cloneable 接口的 `clone()` 方法,然后再调用 `clone()` 方法(`ClonePerson p2 = (ClonePerson) p1.clone()`)。
## 07、ending
>拓展阅读:[浅拷贝与深拷贝](https://tobebetterjavaer.com/basic-extra-meal/deep-copy.html)
### 07、ending
“二哥,我能问一些问题吗?”三妹精神焕发,没有丝毫的疲惫。
......
---
title: 这次彻底搞清楚了 Java 的三大特征之一:封装
shortTitle: 这次彻底搞清楚 Java 封装
title: 聊聊Java封装
shortTitle: Java 封装
description: Java程序员进阶之路,小白的零基础Java教程,认真聊聊 Java的三大特征:封装
category:
- Java 核心
......@@ -12,7 +12,11 @@ head:
content: Java,Java SE,Java基础,Java教程,Java程序员进阶之路,Java入门,教程,java封装
---
## 关于封装
# 5.14 Java封装
“三妹,准备好了没,我们这节来讲 Java 封装,算是 Java 的三大特征之一,理清楚了,对以后的编程有较大的帮助。”我对三妹说。
“好的,哥,准备好了。”三妹一边听我说,一边迅速地打开了 XMind,看来一边学习一边总结思维导图这个高效的学习方式三妹已经牢记在心了。
封装从字面上来理解就是包装的意思,专业点就是信息隐藏,**是指利用抽象将数据和基于数据的操作封装在一起,使其构成一个不可分割的独立实体**
......@@ -27,9 +31,11 @@ head:
- 3、可以对成员进行更精确的控制。
- 4、隐藏信息,实现细节。
首先我们先来看两个类:Husband.java、Wife.java
首先我们先来看两个类
```
Husband.java
```java
public class Husband {
/*
......@@ -74,7 +80,9 @@ public class Husband {
}
```
```
Wife.java
```java
public class Wife {
private String name;
private int age;
......@@ -112,7 +120,9 @@ public class Wife {
}
```
可以看得出, Husband 类里面的 wife 属性是没有 getter()的,同时 Wife 类的 age 属性也是没有 getter()方法的。至于理由我想各位都懂的,男人嘛深屋藏娇妻嘛,还有就是没有哪个女人愿意别人知道她的年龄的。
可以看得出, Husband 类里面的 wife 属性是没有 getter()的,同时 Wife 类的 age 属性也是没有 getter()方法的。至于理由我想三妹你是懂的。
没有哪个女人愿意别人知道她的年龄。
所以封装把一个对象的属性私有化,同时提供一些可以被外界访问的属性的方法,如果不想被外界方法,我们大可不必提供方法给外界访问。
......@@ -126,7 +136,7 @@ public class Wife {
通过这个我们还不能真正体会封装的好处。现在我们从程序的角度来分析封装带来的好处。如果我们不使用封装,那么该对象就没有 setter()和 getter(),那么 Husband 类应该这样写:
```
```java
public class Husband {
public String name ;
public String sex ;
......@@ -137,16 +147,16 @@ public class Husband {
我们应该这样来使用它:
```
```java
Husband husband = new Husband();
husband.age = 30;
husband.name = "张三";
husband.sex = "男"; //貌似有点儿多余
```
但是哪天如果我们需要修改 Husband,例如将 age 修改为 String 类型的呢?你只有一处使用了这个类还好,如果你有几十个甚至上百个这样地方,你是不是要改到崩溃。如果使用了封装,我们完全可以不需要做任何修改,只需要稍微改变下 Husband 类的 setAge()方法即可。
但是哪天如果我们需要修改 Husband,例如将 age 修改为 String 类型的呢?你只有一处使用了这个类还好,如果你有几十个甚至上百个这样地方,你是不是要改到崩溃。如果使用了封装,我们完全可以不需要做任何修改,只需要稍微改变下 Husband 类的 setAge()方法即可。
```
```java
public class Husband {
/*
......@@ -180,7 +190,7 @@ public class Husband {
还是那个 Husband,一般来说我们在引用这个对象的时候是不容易出错的,但是有时你迷糊了,写成了这样:
```
```java
Husband husband = new Husband();
husband.age = 300;
```
......@@ -189,7 +199,7 @@ husband.age = 300;
但是使用封装我们就可以避免这个问题,我们对 age 的访问入口做一些控制(setter)如:
```
```java
public class Husband {
/*
......@@ -221,7 +231,7 @@ public class Husband {
上面都是对 setter 方法的控制,其实通过封装我们也能够对对象的出口做出很好的控制。例如性别在数据库中一般都是以 1、0 的方式来存储的,但是在前台我们又不能展示 1、0,这里我们只需要在 getter()方法里面做一些转换即可。
```
```java
public String getSexName() {
if("0".equals(sex)){
sexName = "女";
......@@ -229,16 +239,13 @@ public String getSexName() {
else if("1".equals(sex)){
sexName = "男";
}
else{
sexName = "人妖???";
}
return sexName;
}
```
在使用的时候我们只需要使用 sexName 即可实现正确的性别显示。同理也可以用于针对不同的状态做出不同的操作。
```
```java
public String getCzHTML(){
if("1".equals(zt)){
czHTML = "<a href='javascript:void(0)' onclick='qy("+id+")'>启用</a>";
......@@ -250,7 +257,9 @@ public String getCzHTML(){
}
```
好了,关于封装我们就暂时聊这么多。
“好了,关于封装我们就暂时就聊这么多吧。”我喝了一口普洱茶后,对三妹说。
“好的,哥,我懂了。”
> 参考链接:[https://www.cnblogs.com/chenssy/p/3351835.html](https://www.cnblogs.com/chenssy/p/3351835.html),整理:沉默王二
......
此差异已折叠。
---
title: Java内部类详解:成员内部类、局部内部类、匿名内部类、静态内部类
shortTitle: Java内部类详解
title: 聊聊Java内部类:成员内部类、局部内部类、匿名内部类、静态内部类
shortTitle: Java内部类
description: Java程序员进阶之路,小白的零基础Java教程,Java内部类详解:成员内部类、局部内部类、匿名内部类、静态内部类
category:
- Java 核心
......@@ -9,15 +9,12 @@ tag:
head:
- - meta
- name: keywords
content: Java,Java SE,Java基础,Java教程,Java程序员进阶之路,Java入门,教程,内部类,成员内部类,局部内部类,匿名内部类,静态内部类
content: Java,Java SE,Java基础,Java教程,Java程序员进阶之路,Java入门,教程,内部类,成员内部类,局部内部类,匿名内部类,静态内部类,java 内部类
---
# 5.13 Java内部类
## 内部类简介
在 Java 中,可以将一个类定义在另外一个类里面或者一个方法里面,这样的类叫做内部类。
一般来说,内部类分为成员内部类、局部内部类、匿名内部类和静态内部类。
“在 Java 中,可以将一个类定义在另外一个类里面或者一个方法里面,这样的类叫做内部类。”我放下手中的枸杞杯,对三妹说,“一般来说,内部类分为成员内部类、局部内部类、匿名内部类和静态内部类。”
### **1)成员内部类**
......@@ -175,10 +172,9 @@ public class Wangsi {
![](https://cdn.tobebetterjavaer.com/tobebetterjavaer/images/oo/inner-class-69523196-37fe-43c6-a52e-5a8c94fdd2d8.png)
“为什么要使用内部类呢?”三妹问。
## 总结
为什么要使用内部类?
三妹这个问题问的非常妙,是时候引经据典了。
在《Think in java》中有这样一句话:
......@@ -186,7 +182,7 @@ public class Wangsi {
在我们程序设计中有时候会存在一些使用接口很难解决的问题,这个时候我们可以利用内部类提供的、可以继承多个具体的或者抽象的类的能力来解决这些程序设计问题。可以这样说,接口只是解决了部分问题,而内部类使得多重继承的解决方案变得更加完整。
使用内部类还能够为我们带来如下特性(摘自《Think in java》)
使用内部类还能够为我们带来如下特性:
- 1、内部类可以使用多个实例,每个实例都有自己的状态信息,并且与其他外围对象的信息相互独立。
- 2、在单个外部类中,可以让多个内部类以不同的方式实现同一个接口,或者继承同一个类。
......
......@@ -9,25 +9,28 @@ tag:
head:
- - meta
- name: keywords
content: Java,Java SE,Java基础,Java教程,Java程序员进阶之路,Java入门,教程,接口
content: Java,Java SE,Java基础,Java教程,Java程序员进阶之路,Java入门,教程,接口,java 接口,java interface
---
“今天开始讲 Java 的接口。”我对三妹说,“对于面向对象编程来说,抽象是一个极具魅力的特征。如果一个程序员的抽象思维很差,那他在编程中就会遇到很多困难,无法把业务变成具体的代码。在 Java 中,可以通过两种形式来达到抽象的目的,一种上一篇的主角——[抽象类](https://tobebetterjavaer.com/oo/abstract.html),另外一种就是今天的主角——接口。”
# 5.11 Java接口
“二哥,开讲之前,先恭喜你呀。我看你朋友圈说《Java程序员进阶之路》开源知识库收到了第一笔赞赏呀,虽然只有一块钱,但我也替你感到开心。”三妹的脸上洋溢着自信的微笑,仿佛这钱是打给她的一样。
“今天开始讲 Java 的接口。”我对三妹说,“对于面向对象编程来说,抽象是一个极具魅力的特征。如果一个程序员的抽象思维很差,那他在编程中就会遇到很多困难,无法把业务变成具体的代码。在 Java 中,可以通过两种形式来达到抽象的目的,一种上一篇的主角——[抽象类](https://tobebetterjavaer.com/oo/abstract.html),另外一种就是今天的主角——[接口](https://tobebetterjavaer.com/oo/interface.html)。”
“二哥,开讲之前,先恭喜你呀。我看你朋友圈说《[Java进阶之路](https://github.com/itwanger/toBeBetterJavaer)》开源知识库在 GitHub 上收到了第一笔赞赏呀,虽然只有一块钱,但我也替你感到开心。”三妹的脸上洋溢着自信的微笑,仿佛这钱是打给她的一样。
![](https://cdn.tobebetterjavaer.com/tobebetterjavaer/images/object-class/interface-01.png)
>PS:2021-04-29到2023-02-11期间,《二哥的 Java 进阶之路》收到了 58 笔赞赏,真的非常感谢大家的认可和支持😍,我会继续肝下去的。
“是啊,早上起来的时候看到这条信息,还真的是挺开心的,虽然只有一块钱,但是开源的第一笔,也是我人生当中的第一笔,真的非常感谢这个读者,值得纪念的一天。”我自己也掩饰不住内心的激动。
“有了这份鼓励,我相信你更新下去的动力更足了!”三妹今天说的话真的是特别令人喜欢。
![](https://cdn.tobebetterjavaer.com/tobebetterjavaer/images/object-class/interface-02.png)
“是呀是呀,让我们开始吧!”
## 定义接口
### 01、定义接口
“接口是什么呀?”三妹顺着我的话题及时的插话到。
......@@ -79,7 +82,7 @@ public interface Electronic
接下来,我来一一解释下 Electronic 接口中的核心知识点。
1)接口中定义的变量会在编译的时候自动加上 `public static final` 修饰符(注意看一下反编译后的字节码),也就是说上例中的 LED 变量其实就是一个常量。
**1)接口中定义的变量会在编译的时候自动加上 `public static final` 修饰符**(注意看一下反编译后的字节码),也就是说上例中的 LED 变量其实就是一个常量。
Java 官方文档上有这样的声明:
......@@ -89,15 +92,15 @@ Java 官方文档上有这样的声明:
不过,这种选择并不可取。因为接口的本意是对方法进行抽象,而常量接口会对子类中的变量造成命名空间上的“污染”。
2)没有使用 `private``default` 或者 `static` 关键字修饰的方法是隐式抽象的,在编译的时候会自动加上 `public abstract` 修饰符。也就是说上例中的 `getElectricityUse()` 其实是一个抽象方法,没有方法体——这是定义接口的本意。
**2)没有使用 `private`、`default` 或者 `static` 关键字修饰的方法是隐式抽象的**,在编译的时候会自动加上 `public abstract` 修饰符。也就是说上例中的 `getElectricityUse()` 其实是一个抽象方法,没有方法体——这是定义接口的本意。
3)从 Java 8 开始,接口中允许有静态方法,比如说上例中的 `isEnergyEfficient()` 方法。
**3)从 Java 8 开始,接口中允许有静态方法**,比如说上例中的 `isEnergyEfficient()` 方法。
静态方法无法由(实现了该接口的)类的对象调用,它只能通过接口名来调用,比如说 `Electronic.isEnergyEfficient("LED")`
接口中定义静态方法的目的是为了提供一种简单的机制,使我们不必创建对象就能调用方法,从而提高接口的竞争力。
4)接口中允许定义 `default` 方法也是从 Java 8 开始的,比如说上例中的 `printDescription()` 方法,它始终由一个代码块组成,为,实现该接口而不覆盖该方法的类提供默认实现。既然要提供默认实现,就要有方法体,换句话说,默认方法后面不能直接使用“;”号来结束——编译器会报错。
**4)接口中允许定义 `default` 方法**也是从 Java 8 开始的,比如说上例中的 `printDescription()` 方法,它始终由一个代码块组成,为,实现该接口而不覆盖该方法的类提供默认实现。既然要提供默认实现,就要有方法体,换句话说,默认方法后面不能直接使用“;”号来结束——编译器会报错。
![](https://cdn.tobebetterjavaer.com/tobebetterjavaer/images/object-class/interface-03.png)
......@@ -114,7 +117,7 @@ Java 官方文档上有这样的声明:
除此之外,我们还应该知道:
1)接口不允许直接实例化,否则编译器会报错。
**1)接口不允许直接实例化**,否则编译器会报错。
![](https://cdn.tobebetterjavaer.com/tobebetterjavaer/images/object-class/interface-04.png)
......@@ -140,7 +143,7 @@ public class Computer implements Electronic {
Electronic e = new Computer();
```
2)接口可以是空的,既可以不定义变量,也可以不定义方法。最典型的例子就是 Serializable 接口,在 `java.io` 包下。
**2)接口可以是空的**,既可以不定义变量,也可以不定义方法。最典型的例子就是 Serializable 接口,在 `java.io` 包下。
```java
public interface Serializable {
......@@ -149,19 +152,21 @@ public interface Serializable {
Serializable 接口用来为序列化的具体实现提供一个标记,也就是说,只要某个类实现了 Serializable 接口,那么它就可以用来序列化了。
3)不要在定义接口的时候使用 final 关键字,否则会报编译错误,因为接口就是为了让子类实现的,而 final 阻止了这种行为。
**3)不要在定义接口的时候使用 final 关键字**,否则会报编译错误,因为接口就是为了让子类实现的,而 final 阻止了这种行为。
![](https://cdn.tobebetterjavaer.com/tobebetterjavaer/images/object-class/interface-05.png)
4)接口的抽象方法不能是 private、protected 或者 final,否则编译器都会报错。
**4)接口的抽象方法不能是 private、protected 或者 final**,否则编译器都会报错。
![](https://cdn.tobebetterjavaer.com/tobebetterjavaer/images/object-class/interface-06.png)
5)接口的变量是隐式 `public static final`(常量),所以其值无法改变。
**5)接口的变量是隐式 `public static final`(常量)**,所以其值无法改变。
### 02、接口的作用
“接口可以做什么呢?”三妹见缝插针,问的很及时。
第一,使某些实现类具有我们想要的功能,比如说,实现了 Cloneable 接口的类具有拷贝的功能,实现了 Comparable 或者 Comparator 的类具有比较功能。
**第一,使某些实现类具有我们想要的功能**,比如说,实现了 Cloneable 接口的类具有拷贝的功能,实现了 Comparable 或者 Comparator 的类具有比较功能。
Cloneable 和 Serializable 一样,都属于标记型接口,它们内部都是空的。实现了 Cloneable 接口的类可以使用 `Object.clone()` 方法,否则会抛出 CloneNotSupportedException。
......@@ -206,7 +211,7 @@ Exception in thread "main" java.lang.CloneNotSupportedException: com.cmower.bael
```
第二,Java 原则上只支持单一继承,但通过接口可以实现多重继承的目的
**第二,Java 原则上只支持单一继承,但通过接口可以实现多重继承的目的**
如果有两个类共同继承(extends)一个父类,那么父类的方法就会被两个子类重写。然后,如果有一个新类同时继承了这两个子类,那么在调用重写方法的时候,编译器就不能识别要调用哪个类的方法了。这也正是著名的菱形问题,见下图。
......@@ -244,7 +249,7 @@ public class Pig implements Fly,Run{
在某种形式上,接口实现了多重继承的目的:现实世界里,猪的确只会跑,但在雷军的眼里,站在风口的猪就会飞,这就需要赋予这只猪更多的能力,通过抽象类是无法实现的,只能通过接口。
第三,实现多态
**第三,实现多态**
什么是多态呢?通俗的理解,就是同一个事件发生在不同的对象上会产生不同的结果,鼠标左键点击窗口上的 X 号可以关闭窗口,点击超链接却可以打开新的网页。
......@@ -312,11 +317,11 @@ for (Shape shape : shapes) {
也就意味着,尽管在 for 循环中,shape 的类型都为 Shape,但在调用 `name()` 方法的时候,它知道 Circle 对象应该调用 Circle 类的 `name()` 方法,Square 对象应该调用 Square 类的 `name()` 方法。
### 04、 接口在应用中常见的三种模式
### 03、接口的三种模式
**在编程领域,好的设计模式能够让我们的代码事半功倍**。在使用接口的时候,经常会用到三种模式,分别是策略模式、适配器模式和工厂模式。
1)策略模式
#### 1)策略模式
策略模式的思想是,针对一组算法,将每一种算法封装到具有共同接口的实现类中,接口的设计者可以在不影响调用者的情况下对算法做出改变。示例如下:
......@@ -361,7 +366,7 @@ public class Demo {
`Demo.defend()` 方法可以接受不同风格的 Coach,并根据所传递的参数对象的不同而产生不同的行为,这被称为“策略模式”。
2)适配器模式
#### 2)适配器模式
适配器模式的思想是,针对调用者的需求对原有的接口进行转接。生活当中最常见的适配器就是HDMI(英语:`High Definition Multimedia Interface`,中文:高清多媒体接口)线,可以同时发送音频和视频信号。适配器模式的示例如下:
......@@ -395,7 +400,7 @@ Coach 接口中定义了两个方法(`defend()` 和 `attack()`),如果类
如果我们只需要对其中一个方法进行实现的话,就可以使用一个抽象类作为中间件,即适配器(AdapterCoach),用这个抽象类实现接口,并对抽象类中的方法置空(方法体只有一对花括号),这时候,新类就可以绕过接口,继承抽象类,我们就可以只对需要的方法进行覆盖,而不是接口中的所有方法。
3)工厂模式
#### 3)工厂模式
所谓的工厂模式理解起来也不难,就是什么工厂生产什么,比如说宝马工厂生产宝马,奔驰工厂生产奔驰,A 级学院毕业 A 级教练,C 级学院毕业 C 级教练。示例如下:
......@@ -468,6 +473,12 @@ public class Demo {
依次类推,我们还可以用 BCoach 类实现 Coach 接口,BCoachFactory 类实现 CoachFactory 接口,从而不断地丰富教练的梯队。
“怎么样三妹,一下子接收这么多知识点不容易吧?”
“其实还好啊,二哥你讲的这么细致,我都做好笔记📒了,学习嘛,认真一点,效果就会好很多了。”
三妹这种积极乐观的态度真的让我感觉到“付出就会有收获”,💪🏻。
----
......
......@@ -12,9 +12,9 @@ head:
content: Java,Java SE,Java基础,Java教程,Java程序员进阶之路,Java入门,教程,java native,java本地方法,java native method
---
# 5.5 Java中的本地方法
# 5.6 Java中的本地方法
“三妹,之前我们学习了 Java 中的基本方法,其实 Java 还有一种方法,本地方法,或者叫 native 方法,它与之前的方法有很大的不同。”我放下手中的手机,扭过脸来对三妹说。
“三妹,之前我们学习了 Java 中的[基本方法](https://tobebetterjavaer.com/oo/method.html),其实 Java 还有一种方法,本地方法,或者叫 native 方法,它与之前的方法有很大的不同。”我放下手中的手机,扭过脸来对三妹说。
“听起来挺有意思的。”三妹很期待。
......@@ -116,7 +116,7 @@ public class HelloJNI {
我们就需要对这个方法进行初始化,所以用了 [static 代码块进行初始化](https://tobebetterjavaer.com/oo/static.html),后面会讲到。
#### 2)编译 HelloJNI.java
#### 02)编译 HelloJNI.java
在命令行通过 `javac HelloJNI.java` 来编译源代码。
......
---
title: 几句话,直观解释清楚 Java 多态(三大特征之一)
shortTitle: 几句话直观解释Java多态
title: 聊聊 Java 多态
shortTitle: Java多态
description: Java程序员进阶之路,小白的零基础Java教程,认真聊聊 Java的三大特征:多态
category:
- Java 核心
......@@ -12,15 +12,21 @@ head:
content: Java,Java SE,Java基础,Java教程,Java程序员进阶之路,Java入门,教程,Java多态,多态
---
**多态就是指程序中定义的引用变量所指向的具体类型和通过该引用变量发出的方法调用在编译时并不确定,而是在程序运行期间才确定。**
# 5.16 Java多态
**即一个引用变量倒底会指向哪个类的实例对象,该引用变量发出的方法调用到底是哪个类中实现的方法,必须在由程序运行期间才能决定。**
“三妹啊,前面聊完了 Java 的[封装](https://tobebetterjavaer.com/oo/encapsulation.html)[继承](https://tobebetterjavaer.com/oo/extends-bigsai.html),今天我们来继续聊多态,也是 Java 三大特性的最后一个特性,搞懂它,Java 面向对象编程基本上就能轻松拿捏了。”我对三妹说。
**因为在程序运行时才确定具体的类,这样,不用修改源程序代码,就可以让引用变量绑定到各种不同的类实现上,从而导致该引用调用的具体方法随之改变,即不修改程序代码就可以改变程序运行时所绑定的具体代码,让程序可以选择多个运行状态,这就是多态性。**
“哥,你继续。”
再具体的分析一下
Java 多态是指在面向对象编程中,同一个类的对象在不同情况下表现出不同的行为和状态
## 01、多态是什么
- 子类可以继承父类的属性和方法,子类对象可以直接使用父类中的方法和变量。
- 子类可以对从父类继承的方法进行重新实现,使得子类对象调用这个方法时表现出不同的行为。
- 可以将子类对象赋给父类类型的变量,这样就可以通过父类类型的变量调用子类中重写的方法,实现多态。
“很枯燥,有没有?再具体的分析一下。”
### 01、多态是什么
在我刻板的印象里,西游记里的那段孙悟空和二郎神的精彩对战就能很好的解释“多态”这个词:一个孙悟空,能七十二变;一个二郎神,也能七十二变;他们都可以变成不同的形态,但只需要悄悄地喊一声“变”。
......@@ -60,7 +66,7 @@ class Wanger {
}
```
## 02、多态与后期绑定
### 02、多态与后期绑定
现在,我们来思考一个问题:程序清单1-1在执行 `wanger.write()` 时,由于编译器只有一个 Wanger 引用,它怎么知道究竟该调用父类 Wanger 的 `write()` 方法,还是子类 Wangxiaoer 的 `write()` 方法呢?
......@@ -106,9 +112,9 @@ class Wanger {
多态的这个优秀的特性,让我们在修改代码的时候不必过于紧张,因为多态是一项让程序员“将改变的与未改变的分离开来”的重要特性。
## 03、多态与构造器
### 03、多态与构造方法
在构造中调用多态方法,会产生一个奇妙的结果,我们来看程序清单3-1:
在构造方法中调用多态方法,会产生一个奇妙的结果,我们来看程序清单3-1:
```java
public class Wangxiaosan extends Wangsan {
......@@ -147,15 +153,15 @@ class Wangsan {
为什么?
因为在创建子类对象时,会先去调用父类的构造器,而父类构造器中又调用了被子类覆盖的多态方法,由于父类并不清楚子类对象中的属性值是什么,于是把int类型的属性暂时初始化为 0,然后再调用子类的构造器(子类构造器知道王小二的年龄是 4)。
因为在创建子类对象时,会先去调用父类的构造方法,而父类构造方法中又调用了被子类覆盖的多态方法,由于父类并不清楚子类对象中的属性值是什么,于是把int类型的属性暂时初始化为 0,然后再调用子类的构造方法(子类构造方法知道王小二的年龄是 4)。
## 04、多态与向下转型
### 04、多态与向下转型
向下转型是指将父类引用强转为子类类型;这是不安全的,因为有的时候,父类引用指向的是父类对象,向下转型就会抛出 ClassCastException,表示类型转换失败;但如果父类引用指向的是子类对象,那么向下转型就是成功的。
来看程序清单4-1:
```text
```java
public class Wangxiaosi extends Wangsi {
public void write() {
System.out.println("记住仇恨,表明我们要奋发图强的心智");
......@@ -186,6 +192,10 @@ class Wangsi {
}
```
“好了,三妹,到此为止,我们就将 Java 的三大特性,封装继承多态全部讲完了,希望你能重新把他们梳理一下。”
“好的,二哥,遵命。”三妹顽皮地笑了。
----
最近整理了一份牛逼的学习资料,包括但不限于Java基础部分(JVM、Java集合框架、多线程),还囊括了 **数据库、计算机网络、算法与数据结构、设计模式、框架类Spring、Netty、微服务(Dubbo,消息队列) 网关** 等等等等……详情戳:[可以说是2022年全网最全的学习和找工作的PDF资源了](https://tobebetterjavaer.com/pdf/programmer-111.html)
......
---
title: Java中this和super的用法总结
shortTitle: Java中this和super的用法总结
title: Java中this和super关键字的用法总结
shortTitle: this和super
description: Java程序员进阶之路,小白的零基础Java教程,Java中this和super的用法总结
category:
- Java 核心
......@@ -9,9 +9,10 @@ tag:
head:
- - meta
- name: keywords
content: Java,Java SE,Java基础,Java教程,Java程序员进阶之路,Java入门,教程,this,super
content: Java,Java SE,Java基础,Java教程,Java程序员进阶之路,Java入门,教程,this,super,java this super,java this,java super,this super
---
# 5.17 this和super
“哥,被喊大舅子的感觉怎么样啊?”三妹不怀好意地对我说,她眼睛里充满着不屑。
......@@ -29,7 +30,7 @@ head:
- this 可以作为参数在构造方法中传递;
- this 可以作为方法的返回值,返回当前类的对象。
## 01、 指向当前对象
### 01、 指向当前对象
“三妹,来看下面这段代码。”话音刚落,我就在键盘上噼里啪啦一阵敲。
......@@ -113,9 +114,7 @@ public class WithThisStudent {
“这次,实例变量有值了,在构造方法中,`this.xxx` 指向的就是实例变量,而不再是参数本身了。”我慢吞吞地说着,“当然了,如果参数名和实例变量名不同的话,就不必使用 this 关键字,但我建议使用 this 关键字,这样的代码更有意义。”
## 02、调用当前类的方法
### 02、调用当前类的方法
“仔细听,三妹,看我敲键盘的速度是不是够快。”
......@@ -164,7 +163,7 @@ public class InvokeCurrentClassMethod {
“我们可以在一个类中使用 this 关键字来调用另外一个方法,如果没有使用的话,编译器会自动帮我们加上。”我对自己深厚的编程功底充满自信,“在源代码中,`method2()` 在调用 `method1()` 的时候并没有使用 this 关键字,但通过反编译后的字节码可以看得到。”
## 03、调用当前类的构造方法
### 03、调用当前类的构造方法
“再来看下面这段代码。”
......@@ -226,7 +225,7 @@ hello
![](https://cdn.tobebetterjavaer.com/tobebetterjavaer/images/keywords/20-01.png)
## 04、作为参数在方法中传递
### 04、作为参数在方法中传递
“来看下面这段代码。”
......@@ -259,7 +258,7 @@ com.itwanger.twentyseven.ThisAsParam@77459877
`method2()` 调用了 `method1()`,并传递了参数 this,`method1()` 中打印了当前对象的字符串。 `main()` 方法中打印了 thisAsParam 对象的字符串。从输出结果中可以看得出来,两者是同一个对象。”
## 05、作为参数在构造方法中传递
### 05、作为参数在构造方法中传递
“继续来看代码。”
......@@ -299,7 +298,7 @@ class Data {
10
```
## 06、作为方法的返回值
### 06、作为方法的返回值
“需要休息会吗?三妹”
......@@ -345,7 +344,7 @@ hello
“噢噢噢噢。”三妹意味深长地笑了。
## 07、super 关键字
### 07、super 关键字
“super 关键字的用法主要有三种。”
......
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册