0、前言
在前面几章内容,我们讨论的内容基本上都是Java语言中,面向过程的一些内容(变量、条件判断、循环处理)。下面,我们开始讨论Java中最为重要,也是最核心的面向对象内容(包、接口、类)。
1、作用域
2、Java包(package)
在实际的开发中,我们不会像《笨方法学 Java -03-第一个 Java 程序》中那样直接把代码放到运行程序的根目录中去。因为,一个软件的代码文件是非常多的,有些类名还可能会重复。所以,我们一般会根据项目信息,创建文件夹来管理源代码和class文件。Java中这些文件夹我们称之为:包(package)。

如上图所示,项目entitytools中有多个层级的包,其中入口程序App.java在包net.mickarea.entitytools.entrance 中。代码使用 package关键字来修饰。当App.java 程序需要一些外部包,则通过import来导入外部程序包的类和接口。
3、Java接口(interface)
接口可以理解为对事物行为的一种抽象建模。比如:从人类这个事物,可以提取一些行为,说话、走路、观察等等。
Java设计接口的很大原因,是为了解决面向对象中多重继承的一些问题,比如:菱形继承。首先,Java语言的类不允许多继承。另外,因为接口是抽象的,接口没有实现代码。即使有相同的方法,在实现子类的时候会指向同一段代码。

如上图所示,“中国人”和“美国人”这2个接口继承于人类接口。“说话”这个方法“中国人”和“美国人”2个接口都有,但是具体实现,要看“学生”类。学生类需要实现3个方法。
Java 8 版本之后,引入了一个接口函数的默认实现语法,使用default修饰方法名。关于引入的原因,参考如下,以下文字来源于网路:
“Java 8之前,如果需要在一个已有的接口中添加一个方法,那么所有这个接口的实现类也都必须同时实现这个方法,否则程序将无法正常编译运行。为了解决这一问题,Java8在接口中引入了 default 方法。”
对于这一做法,会出现多重继承问题。比如上图,如果“说话”这个方法,在“中国人”和“美国人”都有default实现。那我们调用的是谁呢?当然,现代的编译器是很先进的。这个代码在编译时,编译器会帮我们检查并报错。
3.1、参考代码(一个接口,一个文件)


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

List的主要应用场景在于对数据进行列式抽象封装,比如:链表、栈、数组等。具体可以参考截图中的实现类信息。
3.2.2、图(Map)
图(Map)是一种常用的“键值对”数据模型接口。它定义了一系列的方法。对于实现该接口的类,都可以保持同样的方法处理。常见的一个实现类就是 HashMap 哈希值图。API描述如下如下:

图的主要应用场景在于对于数据的键、值成对操作。比如:按照键信息,查找值信息;json信息构建,或者缓存的构建等等。
4、Java类(class)
类即一种数据类型,在Java中指一种引用数据类型。另外,Java类的继承,只能单继承。但是,可以实现多个接口(继承用 extends,实现用 implements)。所以,对于一个Java类,如果要获取多种不同的功能,一般是设计接口。
4.1、普通Java类
Java类和Java接口的差异在于,类可以有自己的属性,接口只能定义功能方法。下面是一个完整的普通类。

注意:
(1) 设计上,类的属性设计为私有,可有效隔离业务代码。比如:如果属性在提取时需要做转换格式,那么在getStdId方法处理即可。外部程序,只能看见getStdId方法。设置stdId值的时候也一样,调用setStdId方法。
(2) 构造方法(函数),一般用于初始化处理。它在调用new创建对象时执行。
(3) 像上面这样设计的Java类,称之为:Java bean。
4.2、抽象类
抽象类是一种特殊的Java类。它与普通的Java类的差异只有一点:抽象类可以不实现功能方法。不实现的功能方法由继承该抽象类的子类实现。如下图:


注意:
(1) 抽象类和抽象方法,都需要 abstract 关键字修饰。
(2) 如果使用抽象类实现接口,那么接口就不用写default方法了。
4.3、Java多态(polymorphism)
多态,这一名词,可以简单理解为多种形态的切换。如图:

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

注意:
(1) 多态的处理,在面向接口编程用得比较多。设计者只需要定义好功能方法接口,具体实现交给Java类的实现者。在使用上,只需要留意接口定义了哪些方法。
4.4、常用Java类
4.4.1、字符串处理 String
在日常开发中,我们经常会用到一个引用类型,String。比如下图:


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


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公司官网下载。