目录


包(package)

包 (package) 是组织类的一种方式,使用包的主要目的是保证类的唯一性。也就是说,在同一个包底下,不能存在同名的类。相反,在不同的包底下,能够存在相同名字的类。那么与包有关的关键字有import与package 。


1.import关键字

我们都知道在Java中有许多现成的类放在不同的包底下提供给程序员使用。而类中有能够满足我们需求的实现方法。那么如何才能使用我们所需要的类呢?要使用import关键字来导入该类所在的包。例如:可以使用import java.util.Date 这种方式引入 java.util 这个包中的 Date 类。如果还需要使用java.util包下的其它类时,例如Scanner类,则还需要import java.util.Scanner

如果我们没有导入该包中的类,则还可以写成这种形式:java.util.Date date = new java.util.Date();但是这种写法比较麻烦一些, 仍然建议使用 import 语句导入包。如果我们不单单只想导入java.util当中的Date类,我们也可以写成import java.util. 号代表的是通配符,顾名思义就是能够将该包下的“所有的类”都导入,为什么“所有的类”加上引号呢?这里的“所有的类”指的是我们在程序中调用了java.util包下的类时无需再导java.util.类名,而import java.util.*这种写法能够在我们使用哪个类时就导入包中指定的哪个类,只是无需再导相同的包。但它却又不是将该包底下的所有类都导入进来。

还有特殊情况:因为在不同包底下可以有相同类名,因此如果真的遇到了**想调用不同包底下的相同的类时,两个包都要进行导入才能正常使用。**并且要看清楚编译器提示给我们的是哪个包底下的类。调用类的方法则是 类名.方法名


2.静态导入

使用 import static 可以导入包中的静态的方法和字段。这种情况用的比较少。例如System类中的方法println是静态方法,因此写成下面这种形式:

import static java.lang.System.*;
public class Test {
    public static void main(String[] args) {
        out.println("hello");
   }
}

上面的例子看的有些别扭,但是导入静态的方法有时也会非常方便,例如:

import static java.lang.Math.*;
public class Test {
    public static void main(String[] args) {
        double x = 30;
        double y = 40;
        // 静态导入的方式写起来更方便一些. 
        // double result = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));
        double result = sqrt(pow(x, 2) + pow(y, 2));
        System.out.println(result);
   }
}


3.package关键字

我们既然已经知道了import关键字的作用是导入一个包底下的类,而package关键字就是显示出该类是在哪个包底下的。

基本规则:

  1. 在文件的最上方加上一个 package 语句指定该代码在哪个包中
  2. 包名需要尽量指定成唯一的名字,通常会用公司的域名的颠倒形式(例如com.bit.demo1)
  3. 包名要和代码路径相匹配,例如创建 com.baidu.www 的包, 那么会存在一个对应的路径 com.baidu.www 来存储代码
  4. 如果一个类没有 package 语句, 则该类被放到一个默认包中

当我们创建了多个包时对于某一个类在哪个包底下会显得有点混乱,我们可以在该类的标签处点击鼠标右键后有如图所下的界面:
【JAVA SE】——包、继承、多态、抽象类、接口 ( 巨细!总结 )_包

【JAVA SE】——包、继承、多态、抽象类、接口 ( 巨细!总结 )_抽象类_02

并且当创建时,编译器自动提示将该类在哪个包底下。

注意1:util包中 有很多类,难道 “ impor java.util.*; ” 是一下子全部 都导入吗?

不是的,Java 处理的时候,需要哪个类,它才会给你那个类。
就是说:Java不会提前给你任何类,当你需要某个类的时候,再给你。而且是要一个,给一个。
不会说要一个,给你一大堆。

这也是 Java 和 C 的区别之一。
假设 include
C 通过 include 关键字,将 stdio.h 头文件里面的内容全部都拿过来,导入程序。
这就好比 古时 朝廷 发赈灾款 给 某位大臣,这批钱,你怎么用都行。
而不是 先排大臣过去,碰到一项需要开支的地方,再向朝廷申请 合适的 拨款数目

如果你要问:Java 和 C 那个导入方式好,肯定是java。因为 Java 是用一个,给一个,用不到的,绝对不会 给你。省空间。
不像C一样,一股脑的全给你,管你用不用,这样就会造成空间的浪费,


注意二:

import java.util.*;

【JAVA SE】——包、继承、多态、抽象类、接口 ( 巨细!总结 )_java_03

但是有一个问题,通配符难道是一次性把所有的类都导入了吗?

不是,java 在处理中需要谁才导入谁

在通配符的使用过程中会出现一个问题

import java.util.*;
import java.sql.*;

【JAVA SE】——包、继承、多态、抽象类、接口 ( 巨细!总结 )_抽象类_04

这两个类中都有 Date 包,编译器分辨不清,导致程序出错

这种情况下需要用完整的类名

java.util.Date date = new java.util.Date();

4.创建自己的包

基本规则

  1. 在文件的最上方加上一个 package 语句指定该代码在哪个包中.
  2. 包名需要尽量指定成唯一的名字, 通常会用公司的域名的颠倒形式(例如 com.bit.demo1 ).
  3. 包名要和代码路径相匹配. 例如创建 com.bit.demo1 的包, 那么会存在一个对应的路径 com/bit/demo1 来存储代码
  4. 如果一个类没有 package 语句, 则该类被放到一个默认包中

【JAVA SE】——包、继承、多态、抽象类、接口 ( 巨细!总结 )_抽象类_05

注意:包名必须是小写的,不能是大写的


包的访问权限控制

我们已经了解了类中的 public 和 private. private 中的成员只能被类的内部使用.

如果某个成员不包含 public 和 private 关键字, 此时这个成员可以在包内部的其他类使用, 但是不能在包外部的类使用.

​ 什么情况可以称为包的访问权限:

当你的成员变量不加任何的访问修饰限定词的时候,默认就是一个包的访问权限,只可以在当前包中使用

比如:

【JAVA SE】——包、继承、多态、抽象类、接口 ( 巨细!总结 )_抽象类_06

常见的包(系统包)

  1. java.lang:系统常用基础类(String、Object),此包从JDK1.1后自动导入。
  2. java.lang.reflect:java 反射编程包;
  3. java.net:进行网络编程开发包。
  4. java.sql:进行数据库开发的支持包。
  5. java.util:是java提供的工具程序包。(集合类等) 非常重要
  6. java.io:I/O编程开发包。

面向对象的基本特征

1:继承
特殊类的对象拥有其一般类的全部属性与服务,称作特殊类对一般类的继承。例如,轮船、客轮;人、大人。一个类可以是多个一般类的特殊类,它从多个一般类中继承了属性与服务,这称为多继承。例如,客轮是轮船和客运工具的特殊类。在java语言中,通常我们称一般类为父类(superclass,超类),特殊类为子类(subclass)。但我们要注意java语言是不支持多继承的,它对多继承的实现是通过接口来进行的。

子类继承父类的:大部分成员变量和大部分成员方法(不包括私有变量和私有方法)

2:抽象类和抽象方法
类中有一个abstract修饰符(但要注意只要有抽象方法的类就是抽象类)、父类中存在抽象方法(也可以没有)抽象方法没有方法体并且修饰符一定要是public或者protected,父类不能new出来
所有子类都必须实现这些抽象方法(如果没实现就必须把它也定义成一个抽象方法) 虽然不能new出来但是它可以有自己的static方法。

3:封装

某个类具有很多的方法,很多时候只管调用,不必了解具体实现,我们只要具体的结果这种是典型的“结果导向”
封装有两个含义

  1. 把对象的全部属性和全部服务结合在一起,形成一个不可分割的独立单位(即对象)。
  2. 信息隐蔽,即尽可能隐蔽对象的内部细节,对外形成一个边界〔或者说形成一道屏障〕,只保留有限的对外接口使之与外部发生联系。

封装的优点:

封装的原则在软件上的反映是:要求使对象以外的部分不能随意存取对象的内部数据(属性),从而有效的避免了外部错误对它的”交叉感染”,使软件错误能够局部化,大大减少查错和排错的难度。

4:接口实现多继承
在类中实现接口可以使用关键字implements
在类的继承中,只能做单重继承,而实现接口时,一次则可以实现多个接口,
每个接口间使用逗号“,”分隔。

多态三个条件(继承、重写、父类对象引用指向子类对象)

多态的好处:
1.可替换性(substitutability)。多态对已存在代码具有可替换性。
2.可扩充性(extensibility)。多态对代码具有可扩充性。
3.接口性(interface-ability)。多态是超类通过方法签名,向子类提供了一个共同接口,由子类来完善或者覆盖它而实现的。
4.灵活性(flexibility)。它在应用中体现了灵活多样的操作,提高了使用效率。
5.简化性(simplicity)。多态简化对应用软件的代码编写和修改过程。


一、继承

(1)什么是继承

代码中如果出现“重复代码”往往意味着一定的风险,当我们要修改这段“重复代码”时,可能要修改多处,造成代码的维护性下降。

为了避免这件事情,可以使用面向对象中的一个重要用法——继承

继承的目的是代码重用,类的重用。把多个类之间的共同代码(共同特性)提取出来,放到"父类"中,然后再由各个子类分别继承这个父类,子类会拥有父类的属性和方法,从而就可以把重复代码消灭了。使用的继承关键字是extends

被继承的称为父类/基类/超类,继承的类称为子类/派生类。


(2)语法规则

使用关键字 extern 进行处理,意义:可以对代码重用

代码举例:

class Animal{
    public int age;
    public String name;
    public void eat(){
        System.out.println("eat()");
    }
}
class Dog extends Animal{
    
}
class Bird extends Animal{
    public String wing;
    public void fly(){
        System.out.println("fly()");
    }
}
public class TestDemo1 {
    public static void main(String[] args) {
        Dog dog = new Dog();
        System.out.println(dog.name);
    }

}

↑↑↑↑ Dog 和 Bird 继承了 Animal 的属性(两种的共同属性)

仔细分析, 我们发现 Animal 和 Dog t以及 Bird 这几个类中存在一定的关联关系: ↓↓↓↓

【JAVA SE】——包、继承、多态、抽象类、接口 ( 巨细!总结 )_java_07

  1. 这三个类都具备一个相同的 eat 方法, 而且行为是完全一样的.
  2. 这三个类都具备一个相同的 name 属性, 而且意义是完全一样的.
  3. 从逻辑上讲, Cat 和 Bird 都是一种 Animal (is - a 语义)

继承中的 Dog(Bird) 可以被称为子类/派生类,Animal 可以称为父类/基类/超类,通过 extern 可以继承父类的属性(和现实中的儿子继承父亲的财产类似, 子类也会继承父类的字段和方法, 以达到代码重用的效果)

【JAVA SE】——包、继承、多态、抽象类、接口 ( 巨细!总结 )_面向对象三大特征_08

由于 Dog (Bird) 继承了父类 Animal 的属性,所以这里可以通过 (.)访问父类的属性

public static void main(String[] args) {
        Dog dog = new Dog();
        System.out.println(dog.name);
    }

例如:

【JAVA SE】——包、继承、多态、抽象类、接口 ( 巨细!总结 )_面向对象三大特征_09


注意:

  • 使用 extends 指定父类.
  • Java 中一个子类只能继承一个父类 (而C++/Python等语言支持多继承).
  • 子类会继承父类的所有 public 的字段和方法.
  • 对于父类的 private 的字段和方法, 子类中是无法访问的.
  • 子类的实例中, 也包含着父类的实例. 可以使用 super 关键字得到父类实例的引用
  • 子类在构造的时候,要先帮助父类构造

看最后一个注意事项,当为父类提供一个构造方法时,程序会报错 !!!

>
public Animal(String name, int age){
        this.name = name;
        this.age = age;
    }

报错 error

【JAVA SE】——包、继承、多态、抽象类、接口 ( 巨细!总结 )_抽象类_10

解决方式:子类帮助父类构造,即(子类先调用父类的构造方法

class Dog extends Animal{
    public Dog(String name, int age){
        super(name,age);//调用父类方法
    }
}

使用 super 关键字,先行调用父类,super 为显示调用构造方法

【JAVA SE】——包、继承、多态、抽象类、接口 ( 巨细!总结 )_抽象类_11

那为什么不写构造方法的时候程序不会报错???

因为当不写构造方法的时候,编译器默认生成一个没有参数的构造方法

如下方的构造方法:

public Dog(){
        super();
    }

super 用法总结:

  • super(); 调用父类的构造方法
  • super.func(); 调用父类的方法
  • super.name; 调用父类的成员属性
  • 不能出现在静态方法中,它是依赖对象的
  • super 一定出现在构造方法的第一行,其他方法中不可以

子类继承父类,子类在内存中的情况

【JAVA SE】——包、继承、多态、抽象类、接口 ( 巨细!总结 )_面向对象三大特征_12


(3)访问权限关键字

访问权限图( private | default | protected | public)

No 范围 private default(包权限) protected public
1 同一个包中的同类 ok ok ok ok
2 同一个包中的不同类 no ok ok ok
3 不同包中的子类 no no ok ok
4 不同包中的非子类 no no no ok

1.同一个包中的同一个类:

【JAVA SE】——包、继承、多态、抽象类、接口 ( 巨细!总结 )_接口_13

2.同一个包中的不同类

【JAVA SE】——包、继承、多态、抽象类、接口 ( 巨细!总结 )_java_14

3.不同包的子类(类的继承需要两个类都是public的类

【JAVA SE】——包、继承、多态、抽象类、接口 ( 巨细!总结 )_接口_15

4.不同包的非子类

【JAVA SE】——包、继承、多态、抽象类、接口 ( 巨细!总结 )_包_16


注意事项:

  1. 我们希望类要尽量做到 “封装”, 即隐藏内部实现细节, 只暴露出 必要 的信息给类的调用者.
  2. 因此我们在使用的时候应该尽可能的使用 比较严格 的访问权限. 例如如果一个方法能用 private, 就尽量不要用public.
  3. 另外, 还有一种 简单粗暴 的做法: 将所有的字段设为 private, 将所有的方法设为 public. 不过这种方式属于是对访问权限的滥用, 还是更希望大家能写代码的时候认真思考, 该类提供的字段方法到底给 “谁” 使用(是类内部自己用, 还是类的调用者使用, 还是子类使用).

(4)final 关键字

如果一个类不想被继承,可以把该类设置为被 final 修饰

总结 final 修饰:

  • final 修饰常量,不可被修改
  • final 修饰类,不可被继承
  • final 修饰方法,方法不可重写,属性不可覆盖

1.final关键字修饰常量:常量不可被修改,并且需要赋初值才能使用。例:

final int a = 10; 
a = 20; // 编译出错

2.final关键字修饰类:这个类不能被继承。

final public class Animal { 
 ... 
} 
public class Bird extends Animal { 
 ... 
} 
// 编译出错,Animal无法被继承

我们经常使用的String字符串类就是被final修饰的类,因此它无法被继承。

【JAVA SE】——包、继承、多态、抽象类、接口 ( 巨细!总结 )_接口_17

3.final关键字修饰方法:方法不能够被重写。

public class Animal { 
    final public void fun() {
    }
} 
public class Bird extends Animal { 
    public void func() {
    }
} 
// 编译出错,func方法无法被重写

二、组合

和继承类似, 组合也是一种表达类之间关系的方式, 也是能够达到代码重用的效果。

组合并没有涉及到特殊的语法(诸如 extends 这样的关键字), 仅仅是将一个类的实例作为另外一个类的字段.这是我们设计类的一种常用方式之一.

  • 组合表示 has - a 语义

在刚才的例子中, 我们可以理解成一个学校中 “包含” 若干学生和教师.

  • 继承表示 is - a 语义

在上面的 “动物和猫” 的例子中, 我们可以理解成一只猫也 “是” 一种动物.

例如:

①学校包含两个学生和两个老师

class Teacher{
    String name;
    String subject;
}
class Student{
    String name;
    String num;
}
public class School{
    public Teacher[] teacher=new Teacher[2];
    public Student[] student=new Student[2];
}

②圆中包含原点和半径

class Point{
    
}
class Raduis{
    
}
public class Circle {
    Point point=new Point();
    Raduis raduis=new Raduis();
}