笨方法学 Java -09-包、接口、类的定义与实现
作者:谎言诞行    发布时间:2024年01月10日

0、前言

在前面几章内容,我们讨论的内容基本上都是Java语言中,面向过程的一些内容(变量、条件判断、循环处理)。下面,我们开始讨论Java中最为重要,也是最核心的面向对象内容(包、接口、类)。


1、作用域

参考《笨方法学 Java -05-语法-变量、常量、赋值》


2、Java包(package)

在实际的开发中,我们不会像《笨方法学 Java -03-第一个 Java 程序》中那样直接把代码放到运行程序的根目录中去。因为,一个软件的代码文件是非常多的,有些类名还可能会重复。所以,我们一般会根据项目信息,创建文件夹来管理源代码和class文件。Java中这些文件夹我们称之为:包(package)。

image.png

如上图所示,项目entitytools中有多个层级的包,其中入口程序App.java在包net.mickarea.entitytools.entrance 中。代码使用 package关键字来修饰。当App.java 程序需要一些外部包,则通过import来导入外部程序包的类和接口。


3、Java接口(interface)

接口可以理解为对事物行为的一种抽象建模。比如:从人类这个事物,可以提取一些行为,说话、走路、观察等等。

Java设计接口的很大原因,是为了解决面向对象中多重继承的一些问题,比如:菱形继承。首先,Java语言的类不允许多继承。另外,因为接口是抽象的,接口没有实现代码。即使有相同的方法,在实现子类的时候会指向同一段代码

image.png

如上图所示,“中国人”和“美国人”这2个接口继承于人类接口。“说话”这个方法“中国人”和“美国人”2个接口都有,但是具体实现,要看“学生”类。学生类需要实现3个方法。

Java 8 版本之后,引入了一个接口函数的默认实现语法,使用default修饰方法名。关于引入的原因,参考如下,以下文字来源于网路

“Java 8之前,如果需要在一个已有的接口中添加一个方法,那么所有这个接口的实现类也都必须同时实现这个方法,否则程序将无法正常编译运行。为了解决这一问题,Java8在接口中引入了 default 方法。”

对于这一做法,会出现多重继承问题。比如上图,如果“说话”这个方法,在“中国人”和“美国人”都有default实现。那我们调用的是谁呢?当然,现代的编译器是很先进的。这个代码在编译时,编译器会帮我们检查并报错。

3.1、参考代码(一个接口,一个文件)

image.png

image.png

3.2、常用接口

下面,我们介绍2个Java自带常用的接口:列表 和 图

3.2.1、列表(List)

列表(List)是一种常用的列式数据模型接口。它定义了一系列的方法。对于实现该接口的类,都可以保持同样的方法处理。常见的一个实现类就是 ArrayList 数组列表。它既保留了数组下标的处理,也扩展了列式数据的操作方法。API描述如下如下:

image.png

List的主要应用场景在于对数据进行列式抽象封装,比如:链表、栈、数组等。具体可以参考截图中的实现类信息。

3.2.2、图(Map)

图(Map)是一种常用的“键值对”数据模型接口。它定义了一系列的方法。对于实现该接口的类,都可以保持同样的方法处理。常见的一个实现类就是 HashMap 哈希值图。API描述如下如下:

image.png

图的主要应用场景在于对于数据的键、值成对操作。比如:按照键信息,查找值信息;json信息构建,或者缓存的构建等等。


4、Java类(class)

类即一种数据类型,在Java中指一种引用数据类型。另外,Java类的继承,只能单继承。但是,可以实现多个接口(继承用 extends,实现用 implements)。所以,对于一个Java类,如果要获取多种不同的功能,一般是设计接口。

4.1、普通Java类

Java类和Java接口的差异在于,类可以有自己的属性接口只能定义功能方法。下面是一个完整的普通类

image.png

注意:

(1)   设计上,类的属性设计为私有,可有效隔离业务代码。比如:如果属性在提取时需要做转换格式,那么在getStdId方法处理即可。外部程序,只能看见getStdId方法。设置stdId值的时候也一样,调用setStdId方法。

(2)   构造方法(函数),一般用于初始化处理。它在调用new创建对象时执行。

(3)   像上面这样设计的Java类,称之为:Java bean

4.2、抽象类

抽象类是一种特殊的Java类。它与普通的Java类的差异只有一点:抽象类可以不实现功能方法。不实现的功能方法由继承该抽象类的子类实现。如下图:

image.png

image.png

注意:

(1)   抽象类和抽象方法,都需要 abstract 关键字修饰。

(2)   如果使用抽象类实现接口,那么接口就不用写default方法了。

4.3、Java多态(polymorphism)

多态,这一名词,可以简单理解为多种形态的切换。如图:

image.png

上面的学生类,实现了3个接口。那么,学生类创建的对象,它既是学生,也是中国人,也是人类

image.png

注意:

(1)   多态的处理,在面向接口编程用得比较多。设计者只需要定义好功能方法接口,具体实现交给Java类的实现者。在使用上,只需要留意接口定义了哪些方法。

4.4、常用Java类

4.4.1、字符串处理 String

在日常开发中,我们经常会用到一个引用类型,String。比如下图:

image.png

image.png

4.4.2、系统信息以及基础输入、输出System

image.png

image.png


5、Java 泛型(generics)

泛型这个概念是从Java 5 开始增加的。

在Java 5 之前,当我们写代码会遇到一种情况:在操作容器接口(List,Map,Set)里面元素的时候,因为都是对象(Object),需要自己转换类型。这对于写代码很麻烦。

因此,在Java 5 的时候,引进了泛型这个概念。泛型,顾名思义是一个泛化的参数类型

其实,泛型的使用是很简单的,就像上图Set<String>,它明确了Set集合里面装的是String类型的元素,因此,不用自己判断类型和类型转换了。

对于带由泛型的函数和类的编写,可以参考这篇文章 https://www.runoob.com/java/java-generics.html


6、综合练习代码

package cn.com.mytest.test.interfaces;
 
//人类信息接口
public interface IHuman {
       //默认方法-- 说话
       default String say() {
              return "我是人类,我在说话...";
       }
}
package cn.com.mytest.test.interfaces;
 
//接口--中国人 继承了 接口--人类
public interface IChinese extends IHuman {
       //抽象方法--说中文
       public String speakChinese();
}
package cn.com.mytest.test.interfaces;
 
//接口--中国人 继承了 接口--人类
public interface IAmerican extends IHuman {
       //抽象方法--说中文
       public String speakEnglish();
}
package cn.com.mytest.test.abclasses;
 
public abstract class MyStudent {
       private String nickName;
       public String getNickName() {
              return nickName;
       }
       public void setNickName(String nickName) {
              this.nickName = nickName;
       }
       public MyStudent() {
              // TODO Auto-generated constructor stub
       }
       public abstract String run();
}
package cn.com.mytest.test.beans;
 
import cn.com.mytest.test.abclasses.MyStudent;
import cn.com.mytest.test.interfaces.IAmerican;
import cn.com.mytest.test.interfaces.IChinese;
 
public class Student extends MyStudent implements IChinese, IAmerican  {
       //学生编号
       private String stdId;
       //构造函数
       public Student() {
       }
       public Student(String stdId) {
              this.stdId = stdId;
       }
       //getter 和 setter 方法
       public String getStdId() {
              return stdId;
       }
       public void setStdId(String stdId) {
              this.stdId = stdId;
       }
       @Override
       public String run() {
              // TODO Auto-generated method stub
              return "学生在奔跑";
       }
       @Override
       public String speakEnglish() {
              // TODO Auto-generated method stub
              return "说英文";
       }
       @Override
       public String speakChinese() {
              // TODO Auto-generated method stub
              return "说中文";
       }
}
package cn.com.mytest.test;
 
import cn.com.mytest.test.beans.Student;
import cn.com.mytest.test.interfaces.IChinese;
import cn.com.mytest.test.interfaces.IHuman;
 
public class App2 {
       public static void main(String[] args) {
              Student s = new Student("学号0001");
              //多态转换
              IHuman h1 = (IHuman)s;
              System.out.println(h1.say());
              //多态转换
              IChinese c1 = (IChinese)h1;
              System.out.println(c1.speakChinese());
       }
}
package cn.com.mytest.test;
 
import java.util.Set;
 
public class App3 {
       public static void main(String[] args) {
              Set<String> keys = System.getenv().keySet();
              for(String key: keys) {
                     System.out.println("key="+key+", value="+System.getenv().get(key));
              }
       }
}


7、Java 8 api 文档介绍

通过前文的内容,大家应该已经对Java语言有多了解。下面我们介绍Java语言的官方API文档。这是在线API地址https://docs.oracle.com/javase/8/docs/api/。如果希望获得离线API文档,可以到Oracle公司官网下载。


填写一种颜色的字符(不区分大小写),1分钟有效,点击图片刷新