1. 类名: 使用名词,采用驼峰命名法(每个单词首字母大写,例如 Car, Person)。

    public class MyClass {
    // class body
    }
  2. 方法名: 使用动词,采用驼峰命名法(第一个单词小写,后面的单词首字母大写,例如 calculateTotalRevenue(), getUserName())。

    public void doSomething() {
    // method body
    }
  3. 变量名: 采用驼峰命名法,描述性强,尽量避免使用单个字符。

    int itemCount;
    String userName;
  4. 常量名: 全部大写,用下划线分隔单词。

    public static final int MAX_SIZE = 100;
  5. 包名: 全部小写,且是反向域名。

    package com.example.myproject;
  6. 接口名: 与类名类似,采用驼峰命名法。

    public interface MyInterface {
    // interface body
    }
  7. 枚举类型名: 采用驼峰命名法。

    public enum DayOfWeek {
    // enum constants
    }
  8. 方法参数: 采用驼峰命名法,尽量使用描述性的名称。

    public void calculateTotal(int itemCount) {
    // method body
    }
  9. 布尔类型变量: 命名时通常使用is、has、can等前缀,以清晰表示其含义。

    boolean isFinished;

1. 一、Java数据类型

1.1. (一)、基本内容

Java的数据类型与C语言十分相似,各种运算符也相似

Java中有多种数据类型可供使用。其中,基本数据类型包括整型(byte、short、int、long)、浮点型(float、double)、字符型(char)和布尔型(boolean)。除了基本数据类型,Java还提供了引用数据类型,如类(class)、接口(interface)、数组(array)等。根据具体需求,选择适当的数据类型可以提高程序的效率和可读性。

在Java中,整型数据类型用于表示整数值。byte类型占用1个字节,可以表示范围为-128到127的整数;short类型占用2个字节,可以表示范围为-32768到32767的整数;int类型占用4个字节,可以表示范围为-2147483648到2147483647的整数;long类型占用8个字节,可以表示范围为-9223372036854775808到9223372036854775807的整数。

浮点型数据类型用于表示带有小数部分的数值。float类型占用4个字节,可以表示范围为-3.402823e+38到3.402823e+38的数值;double类型占用8个字节,可以表示范围为-1.7976931348623157e+308到1.7976931348623157e+308的数值。

字符型数据类型用于表示单个字符。char类型占用2个字节,可以表示范围为’\u0000’到’\uffff’的字符。

布尔型数据类型用于表示真或假的值。boolean类型占用1个字节,只能表示true或false。

除了基本数据类型,Java还提供了引用数据类型。类是Java中的一种引用数据类型,用于表示对象。类可以包含属性和方法,可以通过实例化来创建对象。

接口是Java中的另一种引用数据类型,用于定义一组方法的规范。接口可以被类实现,实现类必须实现接口中的所有方法。

数组是Java中用于存储多个相同类型元素的引用数据类型。数组的长度是固定的,一旦创建后,不能再改变长度。

根据具体需求,选择适当的数据类型可以提高程序的效率和可读性。如果需要存储整数值,可以选择合适的整型数据类型。如果需要存储带有小数部分的数值,可以选择合适的浮点型数据类型。如果需要存储单个字符,可以选择字符型数据类型。如果需要表示真或假的值,可以选择布尔型数据类型。如果需要存储多个相同类型元素,可以选择数组。

数据类型 大小 (字节) 范围(整数) 范围(浮点数) 描述
byte 1 -128 到 127 - 有符号整数,占用1个字节
short 2 -32768 到 32767 - 有符号整数,占用2个字节
int 4 -2147483648 到 2147483647 - 有符号整数,占用4个字节
long 8 -9223372036854775808 到 9223372036854775807 - 有符号整数,占用8个字节
float 4 -3.402823e+38 到 3.402823e+38 - 单精度浮点数,占用4个字节
double 8 -1.7976931348623157e+308 到 1.7976931348623157e+308 - 双精度浮点数,占用8个字节
char 2 ‘\u0000’ 到 ‘\uffff’ - Unicode字符,占用2个字节
boolean 1 true 或 false - 布尔值,占用1个字节
引用类型 - - - 包括类(class)、接口(interface)、数组(array)等

1.2. (二)、类型转换

整型、浮点型、字符型数据可以混合运算。
运算中,不同类型的数据先转化为同一类型,然后进行运算。

1.2.1. 1、自动类型转换

低————————————————————————————————————> 高
byte——> short, char ——> int ——> long ——> float ——> double

1.2.2. 2、强制类型转换

低————————————————————————————————————> 高
byte——> short, char ——> int ——> long ——> float ——> double

整数的默认类型是int
float 类型时必须在数字后面跟上 F 或者 f
使用long 类型时必须在数字后面跟上 L

1.3. (三)小练习

【练习 1 】 请用 Java 实现如下小程序:

(1)火车在计算托运行李费用时以kg 为单位计算费用 12 元 /kg 忽略重量中的小数部分 即忽略不足 1 kg 的部分 。

(2)汽车在计算托运行李费用时以kg 为单位计算费用 22 元 /kg 将重量中的小数部分进行四舍五入

(3)飞机在计算托运行李费用时以g 为单位计算费用 0 062 元 /g 将重量中的小数部分 即不足 1 g 的部分进行四舍五入 。 请设计一个程序 :

让用户从键盘输入行李重量 以 kg 为单位 然后程序分别计算出用火车 、 汽车和飞机托运行李的费用 。火车,12 元 /kg ,小数忽略;汽车,22 元 /kg ,小数四舍五入;飞机,0.062 元 /g ,小数四舍五入

import java.util.Scanner;

public class Main {

public static void main(String[] args) {

Scanner scanner = new Scanner(System.in);
System.out.print("请输入行李重量(kg):");
double weight = scanner.nextDouble();

// 计算火车托运费用(小数部分忽略)
double trainCost = calculateTrainCost(weight);
System.out.println("火车托运费用:" + trainCost + " 元");

// 计算汽车托运费用(小数四舍五入)
double carCost = calculateCarCost(weight);
System.out.println("汽车托运费用:" + carCost + " 元");

// 计算飞机托运费用(小数四舍五入)
double planeCost = calculatePlaneCost(weight);
System.out.println("飞机托运费用:" + planeCost + " 元");
}

// 计算火车托运费用
private static double calculateTrainCost(double weight) {
return Math.floor(weight) * 12; // 小数部分忽略
}

// 计算汽车托运费用
private static double calculateCarCost(double weight) {
return Math.round(weight) * 22; // 小数四舍五入
}

// 计算飞机托运费用
private static double calculatePlaneCost(double weight) {
return Math.round(weight * 1000) * 0.062; // 小数四舍五入,并将kg转换为g
}
}

1.3.1. 代码解释

  1. 导入 Scanner 类:

    import java.util.Scanner;

    这行代码导入了 Java 的 Scanner 类,用于从用户输入中读取数据。

  2. 定义 Main 类:

    public class Main {}

    这是主类的定义,包含了 main 方法作为程序的入口点。

  3. 获取用户输入:

    Scanner scanner = new Scanner(System.in);
    System.out.print("请输入行李重量(kg):");
    double weight = scanner.nextDouble();

    使用 Scanner 获取用户输入的行李重量(以千克为单位)。

  4. 计算并输出费用:

    double trainCost = calculateTrainCost(weight);
    System.out.println("火车托运费用:" + trainCost + " 元");

    double carCost = calculateCarCost(weight);
    System.out.println("汽车托运费用:" + carCost + " 元");

    double planeCost = calculatePlaneCost(weight);
    System.out.println("飞机托运费用:" + planeCost + " 元");

    分别计算火车、汽车和飞机托运行李的费用,并输出结果。

  5. 费用计算函数:

    private static double calculateTrainCost(double weight) {
    return Math.floor(weight) * 12; // 小数部分忽略
    }

    private static double calculateCarCost(double weight) {
    return Math.round(weight) * 22; // 小数四舍五入
    }

    private static double calculatePlaneCost(double weight) {
    return Math.round(weight * 1000) * 0.062; // 小数四舍五入,并将kg转换为g
    }

2. 二、类与对象

2.1. 软件开发流程

需求分析→软件设计→软件编码软件测试→软件维护→软件部署→软件维护

类是对象的抽象, 对象是类的实例

面向对象编程的主要任务 就是定义对象模型中的各个类

2.2. (一)面向对象的三大特点

1、模块化,隐藏细节 encapsulation

2、代码重用,易扩展 inheritance

3、统一接口 polymorphism

2.3. (二)Java中类的组成

2.3.1. 1、成员变量

成员变量是定义在类中,方法体之外的变量。这种变量在创建对象的时候实例化。成员变量可以被类中方法、构造方法和特定类的语句块访问。

2.3.2. 2、构造方法

每个类都有构造方法。如果没有显式地为类定义构造方法, Java 编译器将会为该类提供一个默认构造方法。在创建一个对象的时候,至少要调用一个构造方法。
构造方法的名称必须与类同名, 一个类可以有多个构造方法 。

2.3.3. 3、成员方法

体现类的行为,这些方法的参数体现了该类可以接收的消息

public class Dog {
String breed;
String name;
int age;

public Dog(String breed, String name, int age) {
this.breed = breed;
this.name = name;
this.age = age;
}
void bark() {
System.out.println("Bark!");
}
void run() {
System.out.println("Run!");
}
void sleep() {
System.out.println("Sleep!");
}
}
public class Main {
public static void main(String[] args) {

Dog myDog = new Dog("Poodle", "Bobby", 3);
System.out.println(myDog.breed);
System.out.println(myDog.name);
System.out.println(myDog.age);
myDog.bark();
myDog.run();
myDog.sleep();
}
}

3. 三、封装

封装是指一种将抽象性函数接口的实现细节部分包装、隐藏起来的方法。封装可以防止一个类的代码和数据被外部类定义的代码随机访问。而要访问该类的代码和数据,必须通过严格的接口控制。

3.1. (一)封装的意义

良好的封装能够减少代码的耦合,抵御变化

从设计上讲,实现了模块化。以类为最小单元,减少修改带来的连锁效应;

从使用上讲,减小了复杂度。代码使用者无需考虑实现细节就能直接使用一个类;

3.2. (二)封装的实现

Java访问权限

private:只能被该类的对象访问。
default:即不加任何访问修饰符,只允许在同一个包中进行访问。
protected:只能被类本身的方法及子类访问,即使子类在不同的包中也可以访问。
public:不仅可以跨类访问,而且允许跨包( package )访问。

权限修饰符 同类 同包 不同包的子类 不同包的非子类
private 😊
default 😊 😊
protected 😊 😊 😊
public 😊 😊 😊 😊

理想的封装状态是:
只有一些精心设计的、注释清晰的接口方法为public

成员变量和其他的方法都是private ,它们组成了一个类的内部实现,与类的外部无关

this关键字

public class Dog {
private String breed;
private String name;
private int age;

//构造函数
public Dog(String breed, String name, int age) {
this.breed = breed;
this.name = name;
this.age = age;
}
}

3.3. (三)源文件的引用

当在一个源文件中定义多个类时,要特别注意这些规则:
一个源文件中只能有一个public
源文件的名称应该和public 类的类名保持一致
如果一个类定义在某个包中,那么package 语句应该在源文件的首行

package animals;
import java.io.*;

import语句和 package 语句对源文件中定义的所有类都有效。在同一源文件中,不能给不同的类不同的包声明。

4. 四、继承 Heritage

继承是一种类和类之间的关系 is a

java中的继承是 单继承 的,一个子类只能继承一个父类,使用 extends 关键字 。
继承是多层级的;共同的祖先java.lang.Object
子类继承了父类中所有非 private 成员方法(除了构造方法 和 所有 非 private 的成员变量) 。

继承是一种类与类的关系,“is a kind of”,是Java编程的基石

1、减少冗余代码,易于修改

2、代码重用、易于扩展

4.1. (一)继承的实现

4.1.1. 1、构造函数Constructor和super

构造函数只可以被调用,不能被继承

super必须作为构造方法的第一条执行语句 。

4.1.2. 2、方法的重写(覆盖)override

外壳不变,核心修改

子类中有和父类中可访问(可继承到子类)的同名&&同返回类型 &&同参数表 的方法,就会 重写(覆盖) 从父类继承来的方法。

public abstract class Shape {

public abstract double getArea();

}
public class Rectangle extends Shape {
private int width;
private int height;

public Rectangle(int w, int h) {
this.width = w;
this.height = h;
}

@Override
public double getArea() {
int area = width * height;
return area;
}

}

4.1.3. 3、方法的重载overload

重载方法名字相同,而参数不同。返回类型可以相同也可以不同。
重载规则
被重载的方法必须 改变参数列表 参数 个数 或 类型 或 顺序 不一样
被重载的方法可以 改变返回类型;
被重载的方法可以 改变访问修饰符;
方法能够在同一个类中或者在其子类中被重载

4.1.4. 4、final关键字

final关键字声明类可以把类定义为不能继承的,即最终类;或者用于修饰方法,该方法不能被子类重写

4.1.5. 5、向上转型

上转型对象可以操作被子类继承和重写的方法,但不能 操作子类新增的成员变量和方法。

A.java

public class A {
public void show(){
System.out.println("A");
}
}

B.java

public class B extends A {
public void show(){
System.out.println("B");
}
void hello(){
System.out.println("Hello");
}
}

Main.java

public class Main {

public static void main(String[] args) {
A a = new A();
a.show(); // prints A
B b = new B();
a = b;
a.show(); // prints B
b.show(); // prints B
//a.hello();//编译时会报错
b.hello();

}
}

输出

A
B
B
Hello

4.2. (二)注意事项

继承是一种强耦合关系,在一定程度上破坏了封装,父类变化了,子类也随之变化;
继承可能造成笨拙的类结构,大量的覆盖(重写)带来不必要的复杂度;
继承很有用,但请慎用继承

4.3. (三)练习


Employee.java

public class Employee {
private String name;
private String deptCode;
private int empNum;
public Employee(String name, String deptCode, int empNum) {
this.name = name;
this.deptCode = deptCode;
this.empNum = empNum;
}
}

FulltimeEmp.java

public class FulltimeEmp extends Employee{
private double baseSalary;
private int workedAge;

public FulltimeEmp(String name, String deptCode, int empNum, double baseSalary, int workedAge) {
super(name, deptCode, empNum);
this.baseSalary = baseSalary;
this.workedAge = workedAge;
}

public double calculateSalary(){
return baseSalary + workedAge * 500;
}
}

ParttimeEmp.java

public class ParttimeEmp extends Employee {
private int hours;

public ParttimeEmp(String name, String deptCode, int empNum, int hours) {
super(name, deptCode, empNum);
this.hours = hours;
}

public double calculateSalary(){
return hours * 50;
}
}

Main.java

public class Main {
public static void main(String[] args) {
FulltimeEmp fte = new FulltimeEmp("John", "IT", 123, 1000, 5);
ParttimeEmp pte = new ParttimeEmp("Mary", "IT", 456, 10);
System.out.println(fte.calculateSalary());// 3500
System.out.println(pte.calculateSalary());// 500
}
}

5. 五、抽象类和方法

5.1. (一)抽象类 abstract class

有的类都是用来描绘对象的,如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类。

具体类:可以被实例化的类
抽象类:不能被实例化的类

抽象类通常只作为继承层次中的超类使用
定义抽象类的基本目的 是提供合适的超类,使其他类可以继承它,以实现共享

5.2. (二)抽象方法 abstract method

如果你想设计这样一个类,该类包含一个特别的成员方法,该方法的具体实现由它的子类确定,那么你可以在父类中声明该方法为抽象方法。
抽象方法只包含一个方法名,而没有方法体。
抽象方法没有定义,方法名后面直接跟一个分号,而不是花括号。

public abstract class Form{
private int posX;
private int posY;
public void getInfo(){
System.out.println("This is a form");
}
public abstract void draw();
}

(1)抽象类中不一定包含抽象方法,但是有抽象方法的类必定是抽象类。
(2)抽象类的子类必须给出抽象类中的抽象方法的具体实现,除非该子类也是抽象类。

public abstract class GroupStrategy {
public abstract int makeGroup(int n);
}
public class EvenOddStrategy extends GroupStrategy{
public int makeGroup(int n) {
if (n % 2 == 0) {
return 0;
}
else {
return 1;
}
}
}
public class ModeThreeStrategy extends GroupStrategy{
public int makeGroup(int n) {
if (n % 3 == 0) {
return 0;
}
else if (n % 3 == 1) {
return 1;
}
else {
return 2;
}
}
}
public class FiveStrategy extends GroupStrategy{
public int makeGroup(int n) {
if (check(n/5)){
return 0;
}
else{
return 1;
}
}

public boolean check(int m){
if (m % 2 == 0) {
return false;
}
else
return true;
}
}
public class GroupInteger {
public static void main(String[] args) {
int n = 10;
GroupStrategy[] strategies = new GroupStrategy[3];
strategies[0] = new FiveStrategy();
strategies[1] = new ModeThreeStrategy();
strategies[2] = new EvenOddStrategy();
for (int i = 0; i < strategies.length; i++) {
System.out.println(strategies[i].makeGroup(n));
}
}
}
1
1
0

虽然GroupStrategy是一个抽象类,但是你可以创建该抽象类的数组,而数组中的元素实际上是属于具体的子类对象,例如FiveStrategyModeThreeStrategyEvenOddStrategy。在Java中,虽然不能直接实例化一个抽象类,但可以创建一个数组,集合或者其他数据结构来持有其子类的对象。这是因为这些数据结构的类型是抽象类,但实际上可以包含其子类的对象。GroupStrategy[] strategies是一个数组,其中的元素是GroupStrategy的子类对象。这样的数组允许你以一种通用的方式处理不同的策略对象,而不用关心具体的实现细节。

6. 六、静态方法与变量

6.1. (一)、概念

一个类可以创建多个实例,每个实例有自己的存储空间;
但静态变量和静态方法属于类所有,关键字 static 声明一个属性或方法是与类相关的,因此也称为“类变量”、“类方法”;
静态变量在程序初始化时被创建,可被该类所有的 实例使用和修改;

6.2. (二)使用场合

某个变量被该类所有实例需要,如定义常量、计数的变量、数组等;
特殊类型的类,没有对应实例,其所需参数都是通过显式参数提供,比如Math 类;
只需访问静态变量的方法可定义为静态方法;
main()也是一个静态方法;

public class test {
static {
System.out.println("test static");
}
public void print(){
System.out.println("test print");
}

public static void main(String[] args){
test st1 = new test();
st1.print();
test st2 = new test();
st2.print();
}
//若去除static关键字,则程序没有入口函数

输出:

test static
test print
test print

6.2.1. (三)练习

6.2.1.1. 1、练习一
public class Point {
public double px,py;

public Point(double px,double py){
this.px=px;
this.py=py;
}

public static double distance(Point a,Point b){
double xdiff , ydiff;
xdiff= a.px-b.px;
ydiff= a.py-b.py;
return Math.sqrt(xdiff*xdiff+ydiff*ydiff);
//return Math.sqrt(Math.pow(p1.px-p2.px,2)+Math.pow(p1.py-p2.py,2));
}

public static double random(double low,double high){
double r =Math.random();
return (low + r*(high-low));
}

public void show(){
System.out.print("x ="+ this.px+'\t');
System.out.println("y = "+this.py);
}

public static boolean equals(Point p,Point q,double epsilon){
return Math.abs(p.px-q.px) < epsilon && Math.abs(p.py-q.py)<epsilon;
}


public static void main(String[] args){
Point a1 = new Point(random(0.0,2.0),random(-1.0,0.0));
a1.show();
Point a2 = new Point(random(-1.0,1.0),random(-2.0,1.0));
a2.show();

//Point a3 = new Point(random(0.0,1.0), random(9.0, 8.0));
//a3.show();
System.out.println(Point.distance (a1,a2));//调用静态方法
//System.out.println(a1.distance(a2));//不能这样调用
System.out.println(Point.equals(a1,a2,0.0001));
}

}

//如果想在另一个类中实现这个主函数那么上面的代码要改为下面的:
//即要用Point.random(0.0,2.0)

import static java.lang.Math.random;

public class Main {
public static void main(String[] args){
Point a1 = new Point(Point.random(0.0,2.0),Point.random(-1.0,0.0));
a1.show();
Point a2 = new Point(Point.random(-1.0,1.0),Point.random(-2.0,1.0));
a2.show();
//Point a3 = new Point(random(0.0,1.0), random(9.0, 8.0));
//a3.show();
System.out.println(Point.distance (a1,a2));//调用静态方法
//System.out.println(a1.distance(a2));//不能这样调用
System.out.println(Point.equals(a1,a2,0.0001));
}
}
6.2.1.2. 2、练习二


在Java中,当你使用System.out.println打印一个对象时,实际上会隐式地调用该对象的toString()方法。Object类是所有类的基类,它有一个默认的toString()方法,返回一个由类名和对象的哈希码组成的字符串。

public class Complex {
private double real;
private double imaginary;

public Complex(double real, double imaginary) {
this.real = real;
this.imaginary = imaginary;
}


//用来格式化输出的函数,@Override toString()函数
/*
在Java中,当你使用System.out.println打印一个对象时,实际上会隐式地调用该对象的toString()方法。Object类是所有类的基类,它有一个默认的toString()方法,返回一个由类名和对象的哈希码组成的字符串。
*/
public String toString() {
if (this.imaginary >= 0) {

if(this.imaginary == 0) return this.real + "";

else if(this.real == 0) return this.imaginary + "*i";
else return this.real + " + " + this.imaginary + "*i";
}
else {
if(this.imaginary == 0) return this.real + "";
else if(this.real == 0) return this.imaginary + "*i";
else
return this.real + " - " + (-this.imaginary) + "*i";
}
}


public static void main(String[] args) {
Complex a = new Complex(1,2);
System.out.println(a);// 1.0 + 2.0i
Complex b= new Complex(0,3);
System.out.println(b);// 3.0i
Complex c= new Complex(3,0);
System.out.println(c);// 3.0
}
}

7. 七、接口 interface

接口是一种不同于类(class )的引用类型,是抽象方法的集合。like a

接口无法被实例化,但是可以被实现。一个实现接口的类,必须实现接口内所描述的所有方法,除非声明为抽象类。

7.1. (一)接口的实现

[public] interface 接口名 [extends] 其他的接口名列表
[public static final]数据类型 常量名 = 值
[public abstract]返回类型 方法名(形参列表)
}

接口是隐式抽象的,当声明一个接口的时候,不必使用abstract 关键字
接口中可以含有变量,变量会被隐式的指定为public static final (用 private 修饰会报编译错误)
接口中的方法会被隐式的指定为public abstract

7.2. (二)接口的功能

1.接口提供了一组功能的命名集合

2.接口定义了不同类交互的标准

3.实现了“多继承”,分离了方法的声明和方法的实现

接口中不能有方法的实现,会报错误

public interface TestInterfrace {
void aMethod(int aValue)
{
System.out.println("Hi Mom");
}
}

接口中可以实现静态方法

public interface TestInterfrace {
void setValue(int aValue);
int getValue();
static void staticMethod() {
System.out.println("TestInterfrace static block");
}
}

类继承接口时用implements,而接口继承接口时用extends

public class A implements TestInterfrace{
int value;

public void setValue(int val){
value=val;
}

public int getValue(){
return value;
}
}
//如果使用下面的形式会报错
public class A extends TestInterfrace
public abstract class C implements TestInterfrace {

public int getValue(){
return 0;
}

public abstract void increment();
}
//Door.java
public abstract class Door {
public abstract void open();
public abstract void close();
}

//Alarmable.java
public interface Alarmable {
public abstract void callAlarm();
public abstract void stopAlarm();
static void print(){
System.out.print("Door is here")
}
}

//AlarmDoor.java
public class AlarmDoor extends Door implements Alarmable {
public void open() {
System.out.println("Door is open");
}
public void close() {
System.out.println("Door is closed");
}
public void callAlarm() {
System.out.println("Alarm is ringing");
}
public void stopAlarm() {
System.out.println("Alarm is stopped");
}

public static void main(String[] args){
AlarmDoor.print();
AlarmDoor door = new AlarmDoor();
door.open();
door.callAlarm();
door.close();
door.stopAlarm();
}
}
//print
Door is here
Door is open
Alarm is ringing
Door is closed
Alarm is stopped

7.3. (三)接口与类的异同

7.3.1. 接口与类相似点:

接口文件保存在.java 结尾的文件中,文件名使用接口名。
接口的字节码文件保存在.class 结尾的文件中。

7.3.2. 接口与类的区别:

接口不能用于实例化对象。
接口没有构造方法。
接口中所有的方法必须是抽象方法
接口只能包含static final 成员变量。
接口不是被类继承了,而是要被类实现。
接口支持多继承。

7.4. (四)概念

接口名作为类型: 以接口名为声明类型的变量,可以被实现了该接口的任一类的对象赋值。可以把 使用实现了某一接口的类创建的对象的引用 赋给该接口声明的接口变量,那么该接口变量就可以调用被类实现的接口的方法。
接口继承
默认方法

public interface Alarmable {
public abstract void callAlarm();
public abstract void stopAlarm();
static void print(){
System.out.println("Door is here");
}
default void print2(){
System.out.println("Door is here");
}
}

标准库中的接口
构建程序构架
设计连接和关闭数据库时,由于数据库不同,相对应的实现方式也会有所差异。
我们在设计用户系统时,可以设计一个接口,包含openDB 和 closeDB无具体实现。

import java.sql.Connection;

public interface DB {
Connection openDB(String url, String user, String pw);
void closeDB();
}
import java.sql.Connection;

public class mysqlDB {
Connection openDB(String url, String user, String pw){
return null;
}
void closeDB(){
System.out.println("mysqlDB is closed");
}
}

8. 八、多态

在代码中为同一 名称的方法(接口)提供 不同 的实现

通过接口实现多态

8.1. 一、定义

编译时多态:方法的重载

运行时多态:

8.2. 二、如何使用多态

8.2.1. 1、为一组类抽象出公共父类或接口

8.2.2. 2、统一方法名

8.2.3. 3、多态在方法中的位置

可以在方法的参数 中传入其父类(或接口)类型,在运行时会根据实际的运行时类型来在方法中进行相应的操作。
多态用于返回值 ,可以在方法的返回值类型上使用其实际返回值的父(接口)类型,不关心返回值的实际类型。

8.2.4. 4、多态的选择

根据具体问题合理选择 使用继承和(或)接口;

多态可以使代码变得更通用,以适应需求的变化;
发现变化,封装变化;预判变化,运用抽象。

public class A {
public String show(D obj){
return ("A and D");
}

public String show(A obj){
return ("A and A");
}
}
public class B extends A{
public String show(B obj){
return ("B and B");
}

public String show(A obj){
return ("B and A");
}
}
public class C extends B{

}
public class D extends B {

}
public class Main {
public static void main(String[] arg){
A a1 = new A();
A a2 = new B();
B b = new B();
C c = new C();
D d = new D();
//System.out.println("0 ----"+a1.show(a1));
System.out.println("1 ----"+a1.show(b));
System.out.println("2 ----"+a1.show(c));
System.out.println("3 ----"+a1.show(d));
System.out.println("4 ----"+a2.show(b));
System.out.println("5 ----"+a2.show(c));
System.out.println("6 ----"+a2.show(d));
System.out.println("7 ----"+ b.show(b));
System.out.println("8 ----"+ b.show(c));
System.out.println("9 ----"+ b.show(d));
}

}
1 ----A and A
2 ----A and A
3 ----A and D
4 ----B and A
5 ----B and A
6 ----A and D
7 ----B and B
8 ----B and B
9 ----A and D

这段代码的执行过程:

class A {
public String show(D obj) {
return ("A and D");
}
public String show(A obj) {
return ("A and A");
}
}

class B extends A {
public String show(B obj) {
return ("B and B");
}
public String show(A obj) {
return ("B and A");
}
}

class C extends B {
}

class D extends B {
}


public class Demoduotai {

public static void main(String[] args) {
A a1 = new A();
A a2 = new B();
B b = new B();
C c = new C();
D d = new D();
System.out.println(a1.show(b));//A and A B向上转型A
System.out.println(a1.show(c));//A and A C向上转型A
System.out.println(a1.show(d)); //A and D
System.out.println();
/*
* A a2 = new B(); 这里a2的引用类型是A,但是它指向的内存是类型为B的一个实例
* 想对a2进行方法调用,
* 你调用的方法都必须在class A里面有的才行 (因为你的引用类型为A)
* 这里 class A有 show(A obj) show(D obj)着两个方法
* a2.show(b) 在class A中没有找到类型匹配的方法,
* 但是对b进行向上转型后, 可以找到 show(A obj)方法
* 但是a2内存地址指向一个类型为B内存空间
* 如果class B Override 了 class A的show(A obj)方法,则调用B的show(A obj)方法
*/
System.out.println(a2.show(b));// class A中没有show(b)这个方法,但是由于B是A的子类,可以进行向上转型为A,可以找到show(A obj)方法,但是a2内存地址指向一个类型为B内存空间,并且classB 重写了class A的show(A obj)方法,则调用B的show(A obj)方法
System.out.println(a2.show(c));// class A中没有show(c)这个方法,但是由于C是B的子类,B是A的之类,可以进行向上转型为A,可以找到show(A obj)方法,但是a2内存地址指向一个类型为B内存空间,并且classB 重写了class A的show(A obj)方法,则调用B的show(A obj)方法
System.out.println(a2.show(d));// class A中没有show(c)这个方法,但是由于D是B的子类,B是A的子类,可以进行向上转型为A,可以找到show(A obj)方法,但是a2内存地址指向一个类型为B内存空间,并且classB 重写了class A的show(A obj)方法,则调用B的show(A obj)方法
System.out.println();
System.out.println(b.show(b));//直接调用B的show(B obj)方法
System.out.println(b.show(c));//C向上转型为B,调用B的show(B obj)方法
System.out.println(b.show(d));//java中这里精准匹配到A的show(D obj)方法,因为A是B的父类;但是在C#中则不会调用B的父类中的方法,因为
} //B b = new B();和A没有关系

}
A and A
A and A
A and D

B and A
B and A
A and D

B and B
B and B
A and D

9. 九、类的关系

9.1. (一)、1+3+1

9.1.1. 1、依赖

简单的理解,就是一个类A 中的方法使用到了另一个类 B 。
这种使用关系是具有偶然性的、临时性的、非常弱的,但是B 类的变化会影响到 A 。
依赖是类之间关系最弱的一种形式 。

public class Person {
void drive(){
......
}
void write(){
Pen p = new Pen();
p.write
}
String getWeather(){
WeatherStation ws = new WeatherStation();
return ws.getState();
}
}

9.1.2. 2、关联

一个类作为另一个类的成员变量出现
关联可以是单向的(导航 ) ,也可以是双向的
关联可以是1 对 1 的,也可以是 1 对多 的,也可以是 多对多 的
一个类使用了被关联类的属性和方法来实现自己的功能
被关联的类若发生改动,则使用它的类也会发生变化

关联体现的是两个类之间比依赖更强的一种关系,一般是长期性的。

public class Person{
private Pen pen;
void write(){
this.pen.write
}
}

9.1.3. 3、组合

与关联关系一样,组合关系也是通过将其它类作为成员变量实现的。
在组合关系中,两个类是有着不同层级的关系的,一个代表整体 ,另一个代表部分 。
整体与部分之间是不可分离的 ,整体的生命周期结束也就意味着部分的生命周期结束 同生共死

组合也是关联关系的一种特例,他体现的是一种contains-a 的关系,这种关系比聚合更强,也称为 强聚合 。
组合同样体现整体与部分间的关系,但此时整体与部分是不可分的,整体的生命周期结束也就意味着部分的生命周期结束。
组合要求普通的聚合关系中代表整体的对象负责代表部分对象的生命周期,因此,组合关系是 不能共享的 。换言之,代表部分的对象在每一个时刻只能与一个对象形成组合关系,由后者负责其生命周期。

9.1.4. 4、聚合

与关联关系一样,聚合关系也是通过将其它类作为成员变量实现的。
在聚合关系中,两个类是处在不同层次上的,一个代表整体 ,另一个代表 部分 。
虽然是整体和部分的关系,但是整体与部分之间是可分离的,他们可以具有各自的生命周期,部分可以属于多个整体对象,也可以被多个整体对象共享。

聚合是关联关系的一种特例,它体现的是整体与部分 的拥有关系,即 has a 的关系;
普通的关联关系中,A 类和 B 类没有必然的联系,而聚合中,需要 B 类是 A 类的一部分,是一种” has a“ 的关系,即 A has a B,但是,has 不是 must has ,整体与部分之间是可分离的,他们可以具有各自的生命周期;

9.1.5. 5、继承

继承 组合
优点 子类能自动继承父类的接口


创建子类的对象时,无须手动 创建父类的对象
不破坏封装,整体类与局部类之间(相对松耦合,彼此相对独立)
具有较好的可扩展性
支持动态组合
在运行时整体对象可以选择不同类型的局部对象
整体类可以对局部类进行包装,封装局部类的接口,提供新的接口
缺点 破坏封装,子类与父类之间紧密耦合
支持扩展,但是往往以增加系统结构的复杂度为代价
不支持动态继承
。 在运行时,子类无法选择不同的父类
子类不能改变父类的接口
整体类不能自动获得和局部类同样的接口
创建整体类的对象时,需要创建所有局部类
的对象

面向对象中有一个重要原则『 多用组合、少用继承 』 或者说 『 组合优于继承 』

10. 十、UML

10.1. (一)、静态模型

用例图(Use Case Diagram ):从用户角度描述系统功能。
类图(Class Diagram ):描述对象模型中类与类之间的关系。
组件图(Component Diagram ):描述系统中各个组件之间的依赖关系,还可以描述组件的源代码组织结构。
部署图(Deployment Diagram ):定义系统中软硬件的物理体系结构。

10.1.1. 1、类图(Class Diagram )


10.1.2. 2、用例图(Use Case Diagram )

用例图显示了系统的功能,由参与者 和 用例 构成
以图形化的方式表示了:
(1)系统内部 的功能
(2)系统外部 的参与者
(3)以及它们之间的交互关系

用例不描述系统内部如何工作,只是定义功能 ,说明系统必须做什么。
一个用例由一系列动作 或 事件 流组成。

软件开发的需求分析 阶段:
(1)识别系统的参与者 ,以及他们对系统的需求;
(2)从系统的需求描述中找出用例以动词短语描述用户与系统交互的 完整 事件流;
(3)对用例进行详细描述(主事件流、其他事件流、前提条件等);
(4)画出系统用例图。

10.1.3. 3、组件图

作用
显示软件系统中组件之间的依赖 关系,以及和 第三方 组件(比如类库)的依赖关系。

还能显示包含软件的源代码文件的物理组织结构。
组件
软件系统中的子系统,它由一组协作完成特定服务的类 组成。
每个组件都封装 实现的细节,对外公开 接口 。
组件之间仅存在依赖关系。

10.1.4. 4、部署图

作用
表示软件系统如何部署到硬件环境中,能够展示系统中的组件在硬件环境中的物理布局 。
节点
一个节点代表一台物理机器,或一个虚拟机器节点;用三维立方体表示;

10.2. (二)动态模型

时序图(Sequence Diagram ):显示对象之间的动态协作关系,强调对象之间消息发送的时间顺序。
活动图(Activity Diagram ):显示活动的顺序控制流。
状态转换图(State Transition Diagram ):描述对象所有可能的状态,以及导致状态转换的条件。

10.2.1. 1、时序图

主要用来显示具体用例 的详细动作或事件流程
时序图为二维图形
•水平维度:显示对象之间发送消息的时间顺序;
•垂直维度:显示发送消息的时间顺序;

10.2.2. 2、活动图

描述活动的顺序,展现从一个活动到另一个活动的控制流

10.2.3. 3、状态转换图

描述一个对象的生命周期中所处的不同状态,以及状态之间的转换过程。

11. 十一、Java标准库

11.1. (一).包与库

11.1.1.1. 1、规则

Java包
避免命名冲突;
可以方便查找与使用;
访问控制;
创建自定义类库,有助于软件重用

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

public class E {
Date date = new Date();
}
//The type Date is ambiguous


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

public class E {
public static void main(String[] args) {
java.util.Date deadLine = new java.util.Date();
java.sql.Date today = new java.sql.Date(System.currentTimeMillis());
System.out.println(deadLine);
System.out.println(today);
}
}

命名
包名需全部小写
包名参考文件夹的层级结构;
公司一般使用域名 反转 作为包名

example.com
com.example.mypackage
11.1.1.2. 2、使用

包名的声明必须出现在第一行
默认包没有名称
父包与子包:
子包需要显式引用
父包不包含子包

11.2. (二).基础类

11.2.1. 1、java.lang.Object

所有类的祖先仅有一个默认构造方法

public Object(){} //

方法体为空主要成员方法:

equals(Object obj ) // 判断是否为同一对象
toString() //返回对象的字符串表示,“类名 对象的十六进制哈希码”

11.2.2. 2、包装类

11.2.2.1. (1)、包装类的构造方法

所有的包装类都可以以它对应的基本数据类型为参数来构造实例

除了Character 类外,都可以以一个字符串为参数来构造实例

Boolean类的构造方法的参数为 String 时,仅当内容为“ true ”时为真(不考虑大小写)

11.2.2.2. (2)、包装类的常用方法

(1)包装类覆盖了 Object 类的 toString 方法,打印时返回对应字符串值
(2)数值类都有 valueOf (String) 静态方法,用于创建包装类对象

Integer i = Integer.valueOf ("123");
Integer i = Integer.valueOf ("abc");

(3)数值类都有 parseXXX (String) 静态方法,用于将字符串转为对应的基本数据类型

double d = Double.parseDouble(“123”);

11.2.3. 3.工具类

12. 十二、java泛型

12.1. 1.泛型的定义

12.2. 2.泛型的分析

12.3. 3.通配符

13. 十三、集合框架

13.1. (一)、Java Collection Framework

接口:代表 着 集合的抽象数据类型。 多级的接口构成了集合框架的标准调用接口。
实现(类):是集合接口的具体实现 可重复使用的数据结构 。
算法:用来 执行一些有用的计算,这些算法 的设计体现了 多态。

Java不提供直接实现 Collection 的类,只提供实现其子接口(如 List 和 set) 的类。

13.2. (二)集合实现

13.2.1. 1、集合的遍历 Set, List, Queue

13.2.1.1. I.for循环
13.2.1.2. II.增强for 循环
13.2.1.3. III.Iterator接口
hasNext
next()
remove(Object o)
import java.util.List;
import java.util.ArrayList;
import java.util.Iterator;
public class FindDups {
public static void main(String[] args ) throws InterruptedException{

List<String> list=new ArrayList <String>();
list.add("hello");
list.add("world");
list.add("again");

//增强for循环
for (String str : list) {
System.out.print(str+'\t');
}
System.out.println();

//for循环
String[] strArray =new String[list.size()];
list.toArray (strArray);
for(int i =0; i<strArray.length;i++){
System.out.print(strArray [i]+'\t');
}Iterator
System.out.println();

//Iterator接口
Iterator <String> it=list.iterator ();
while(it.hasNext()){
System.out.print(it.next()+'\t');
}

}
}

13.2.2. 2、hash集合元素的存取

Hash集合有很好的存取和查找功能。
向集合中加入对象时,会调用hashCode 方法获得哈希码,进而计算出对象在集合中的存放位置。

obj1.equals(obj2);
obj1.hashCode() == obj2.hashCode();

Hash集合要求两个对象用 equals() 方法比较的结果为 true 时, 它们的哈希码也相等 。

import java.util.HashSet;
import java.util.Set;

public class jirkou {
public static void main(String[] args) {
Set<Customer> set = new HashSet <Customer>();
Customer c1 = new Customer("Tom", 15);
Customer c2 = new Customer("Tom", 15);
set.add(c1);
set.add(c2);
System.out.println(set.size());
for(Customer c : set){
//System.out.println(c.getName() + " " + c.getAge());//遍历
System.out.println(c);//打印哈希表,也就是地址
}

}

}

13.2.3. 3、List性能比较

ArrayList是顺序访问的首选
LinkedList可作为栈 Stack 、队列 Queue 和双向队列 Qeque 的实现类

13.2.4. 4、有序集合

TreeSet和 TreeMap 分别实现了 SortedSet 和 SortedMap 接口,能够对集合中的元素排序

自然排序(实现Comparable 的基础类):如 Integer Double 和 String 等

自定义排序(实现Comparable 或 Comparator 的自定义类)

import java.util.Set;
import java.util.TreeSet;

public class jirkou {
public static void main(String[] args) {
Set<Integer> set = new TreeSet<>();
for(int i = 10; i>0; i--){
int a=i*10;
set.add(a);
System.out.print(a+"\t");
}
System.out.println();
for (int i : set) {
System.out.print(i + "\t");
}
}
}

13.3. (三)、集合算法

13.3.1. 1、排序 Sorting

13.3.2. 2、打乱 Shuffling

13.3.3. 3、操作数据 Routine Data Manipulation

13.3.4. 4、查找 Searching

13.3.5. 5、分析 Composition

13.3.6. 6、找极值 Finding Extreme Values

13.3.7. 7、集合与数组相互转化