# Java 介绍

# Java 本身

  • Java 是由 Sun Microsystems 公司于 1995 年 5 月推出的 Java 面向对象程序设计语言和 Java 平台的总称。
  • Java 还是一个标准的类库

类库:可以复用的程序功能

  • 是一个可以在操作系统上和浏览器上运行的运行环境

Java 的特点:

  • 网络能力,国际化的,编译、解释性
  • 面向对象,可移植的 (源代码和二进制级别),高性能(感觉不如 c++),安全的,分布式 (计算) 的,动态的 (热插拔),健壮的,多线程的,体系结构中立,相对年轻,有巨大的发展基础。
  • 编译、解释性:源代码被编译成字节码 (可以被 JVM 识别的机器码,Java 特有的),字节码在 JVM 的解释器上被解释
  • 网络能力:诞生于互联网时期

# Java 历史

  • 1995 年 5 月 23 日,Java 语言诞生
  • 1996 年 1 月,第一个 JDK-JDK1.0 诞生
  • 1997 年 2 月 18 日,JDK1.1 发布
  • 1998 年 12 月 8 日,J2SE1.2 发布,(JAVA2 企业平台 J2EE 发布)
  • 2001 年 9 月 24 日,J2EE1.3 发布
  • 2002 年 2 月 26 日,J2SE1.4 发布
  • 2004 年 9 月 30 日,发布 J2SE1.5 且更名为 Java SE 5.0
  • 2006 年 12 月,SUN 公司发布 JRE6.0
  • 2011 年 7 月 28 日,甲骨文发布 Java7.0 的正式版。(以后稳定 3 月 9 月出新版本)
  • 2014 年 3 月 18 日,Oracle 公司发表 Java SE 8。
  • 2017 年 9 月 21 日,Oracle 公司发表 Java SE 9
  • 2018 年 3 月 21 日,Oracle 公司发表 Java SE 10
  • 2018 年 9 月 25 日,Java SE 11 发布 (长期支持版本,LTS)
  • 2019 年 3 月 20 日,Java SE 12 发布
  • 2019 年 3 月 20 日,Java SE 12 发布
  • 2019 年 3 月 20 日,Java SE 12 发布
  • 2019 年 3 月 20 日,Java SE 12 发布
  • 2019 年 3 月 20 日,Java SE 12 发布
  • 2021 年 9 月 21 日,Java SE 17 (LTS) 发布
    Java版本区别

# Java 执行机制

Java 平台
Java 程序
API
JVM
宿主平台

Java程序执行
源代码 -> 编译器 -> 字节码 ->JVM-> 操作系统

比其他的多个 JVM,所以不同平台的机器码相通

# Java 使用

构建程序和软件组件
程序:应用和小程序
组件:Servlets
JavaServer Pages (JSPs)JavaBeans
Enterprise JavaBeans (EJBs)

# Java 输入与输出

Java输入与输出

# String 与 StringBuilder

# String

# 创建

  • String s1 = “Runoob”; // String 直接创建
    String s2 = “Runoob”; // String 直接创建
    String s3 = s1; // 相同引用
    String s4 = new String (“Runoob”); // String 对象创建
    String s5 = new String (“Runoob”); // String 对象创建

s1 的内容存在静态区域,s2 指向 s1,s3 指向 s2。
s4 与 s5 不相等 (== 或者 equals 返回 false),因为他们指向不同的对象

# 方法

  • 使用 + 或 concat () 连接字符串
  • 使用.length () 返回字符串长度
  • 使用 format 创建格式化字符串
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
>String fs;
>fs = String.format("浮点型变量的值为 " +
"%f, 整型变量的值为 " +
" %d, 字符串变量的值为 " +
" %s", floatVar, intVar, stringVar);
>```

### Stringbuilder
在使用 StringBuffer 类时,每次都会对 StringBuffer 对象本身进行操作,而不是生成新的对象,所以如果需要对字符串进行修改推荐使用 StringBuffer。
StringBuilder 类和 StringBuffer 之间的最大不同在于 StringBuilder 的方法不是线程安全的(不能同步访问)。
#### 创建
- StringBuilder builder = new StringBuilder();
StringBuilder builder = new StringBuilder("abc");
StringBuilder builder = new StringBuilder(初始长度);
#### 方法
- 使用append追加数据`builder.append("just");`
- 删除指定位置的数据`builder.deleteCharAt(index);`
- 删除指定范围的数据左闭右开`builder.delete(beginIndex, endIndex);`
- 将对象中的数据以字符串的形式返回`builder.toString();`
- 返回此序列中指定索引处的 char 值`char charAt(int index)`
- 返回一个新的 String,它包含此序列当前所包含的字符子序列。`String substring(int start, int end)`

### equals详解
#### 定义
- obj.equals(obj2) 若是返回true说明两者引用同一个对象
```java
public boolean equals(Object obj) {
return (this == obj);
}

# equals 注意事项

  • equals 方法不能作用于基本数据类型的变量。
  • String 类对 equals 方法进行了重写,用来比较指向的字符串对象所存储的字符串是否相等。
  • StringBuilder 没有重写 equals 方法,所以比较的还是地址

# equals 与 == 的区别

  • “==” 用来比较基本数据类型(int ,double…)时候是直接比较数值,比较引用数据类型(class, 接口…)的时候比较的是对象的引用和地址
  • 在 Object 类中,equals 方法是用来比较两个对象的引用是否相等,即是否指向同一个对象。
    equals例题
    选择 E

# 内存分配

内存分配图

#

  • new 声明的所有东西
    • 字符串本体
    • 数组元素
    • new 的每一次地址都不同
  • new 的执行过程
    • 首先分配堆内存空间
    • 其次进行值的初始化
      • 如果是基本类型就按规则来(int float 是 0 char 是空字符)
      • 引用类型全是 null(比如自定义类的变量,二维数组)
      • 如果是传入字符串比如 test = new test("abc") 这类
        • 先给 abc 分配空间并填充,再把这个空间的头指针填到 test 里
    • 套娃情况: test[] t = new test{new ClassA a, new ClassB b}
      • 先给 a 和 b 分配空间并填充,再给 t 分配空间并把 ab 的地址填进去

#

  • 基本类型变量( int double char 等等)
    • 值相同地址也相同
  • 数组和字符串的头指针
    • 指向堆里的元素
    • 如果没写赋值则只在栈里留个指针,不指向堆里的内存
    • 写了赋值之后如果是同类型 a = b 这种则指向 b 所在的堆内存
  • 方法生成的临时局部变量

# 静态区

  • 类的静态量(带 static 的)
  • 直接引号声明的字符串
  • 常量(final)
  • 值相同地址也相同

# 创建与声明

# 创建 .java 文件

  • 每个.java 文件都是一个类
    • 如果这个类里面包含一个 main 方法则可以执行
  • 在工作目录下不同的文件夹代表不同的 package

# 包的声明

  • package pkg1.pkg2....pkgn
  • 其中 pkg1 为父文件夹,2~n 为嵌套的子文件夹
1
2
3
4
package net.java.util;
public class Something{
...
}

那么它的路径应该是 net/java/util/Something.java 这样保存的。

# 导入

import pkg

  • 此语句向当前 .java 文件中导入了 pkg 包中的所有类

import pkg.class

  • 此语句向当前 .java 文件中导入了 pkg 包中的 class
    例题四

# 接口的声明

  • 接口存储在一个 .java 文件中
1
2
3
4
interface Animal {
public void eat();
public void travel();
}
  • 接口里的类默认是 public abstract ,并且不能 private

# 方法的声明

方法的声明

  • 方法头就是方法签名,它决定多态里的重写和重载

# 主方法的声明

public static void main(String[] args)

  • public 修饰符:Java 类由 JVM 调用,为了让 JVM 可以自由调用这个 main 方法,所有使用 public 来修饰这个方法。

  • static 修饰符:JVM 调用这个主方法时,不会先创建该主类的对象,然后通过对象来调用该主方法。JVM 直接通过该类来调用主方法,因此使用 static 来修饰。

  • void 返回值:主方法被 JVM 调用,该主方法的返回值将返回给 JVM,这没有任何意义,因此返回值使用 void

  • String [] args:字符串数组形参。

    1. args=arguments 是主方法的形参。该单词可以翻译为 “入口参数”, 这个参数名当然可以任意修改的。
    2. String [] args 这个字符串数组是保存运行 main 函数时输入的参数的,在 cmd 运行 java test a b c 时,会有 args [0] = a ,args [1]=b, args [2]=c 可以在你的程序中调用输入的这些变量。

# 变量的声明

  • 变量类型 + 变量名称
  • 注意不能使用保留字符 开头不能用数字

# 标识符

# 标识符的命名规范

  • 1. 包名:多单词组成的所有的字母都是小写 xxxyyyzzz
  • 2. 类名 接口名多单词组成所有单词的首字母大写 XxxYyyZzz
  • 3. 变量名 方法名多单词组成第一个单词的首字母小写,第二个单词开始每个单词的首字母大写 xxxYyyZzz
  • 4 常量名:所有字母大写多单词用下划线连接 XXX_YYY_ZZZ

# 标识符的命名规则

  • 1. 由 2 个大小写的英文字母 0-9 $ _ 组成
  • 2. 数字不可以开头
  • 3. 不可以使用关键字和保留字,但可以包含关键字和保留字
  • 4.Java 严格区分大小写,长度没有限制
  • 5. 标识符不能包含空格

# Java 关键词

关键字列表

# 基本数据类型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
基本类型:byte 二进制位数:8
包装类:java.lang.Byte
最小值:Byte.MIN_VALUE=-128
最大值:Byte.MAX_VALUE=127

基本类型:short 二进制位数:16
包装类:java.lang.Short
最小值:Short.MIN_VALUE=-32768
最大值:Short.MAX_VALUE=32767

基本类型:int 二进制位数:32
包装类:java.lang.Integer
最小值:Integer.MIN_VALUE=-2147483648
最大值:Integer.MAX_VALUE=2147483647

基本类型:long 二进制位数:64
包装类:java.lang.Long
最小值:Long.MIN_VALUE=-9223372036854775808
最大值:Long.MAX_VALUE=9223372036854775807

基本类型:float 二进制位数:32
包装类:java.lang.Float
最小值:Float.MIN_VALUE=1.4E-45
最大值:Float.MAX_VALUE=3.4028235E38

基本类型:double 二进制位数:64
包装类:java.lang.Double
最小值:Double.MIN_VALUE=4.9E-324
最大值:Double.MAX_VALUE=1.7976931348623157E308

基本类型:char 二进制位数:16
包装类:java.lang.Character
最小值:Character.MIN_VALUE=0
最大值:Character.MAX_VALUE=65535

# 常量

# 定义

  • java 常量就是在程序中固定不变的值,是不能改变的数据。常量包括整型常量、浮点数常量、布尔常量、字符常量等。

# 分类

常量分为静态常量、成员常量和局部常量。

应当与变量作区分

  • 使用 final 前缀
  • 整形常量
    • 十六进制整型常量:以十六进制表示时,需以 0x 或 0X 开头,如 0xff,0X9A。
    • 十进制:由数字 0~9 范围内 (包括 0 和 9) 的整数组成的数字序列。如 198。
    • 八进制整型常量:八进制必须以 0 开头,如 0123,034。
    • 二进制:由数字 0 和 1 组成的数字序列。在 JDK7.0 中允许使用字面值来表示二进制数,前面要以 0b 或 0B 开头,目的是为了和十进制进行区分,如 0b01101100、0B10110101。
    • 长整型:长整型必须以 L 作结尾,如 9L,342L。
  • 浮点数常量:由于小数常量的默认类型是 double 型,所以 float 类型的后面一定要加 f (F)。同样带小数的变量默认为 double 类型。
  • 字符常量:字符型常量需用两个单引号括起来。
  • 字符串常量用于表示一串连续的字符,一个字符串常量要用一对英文半角格式的双引号 "" 引起来
  • 布尔常量即布尔型的两个值 true 和 false,该常量用于区分一个事物的真与假。
  • null 常量只有一个值 null,表示对象的引用为空。

# 常量的声明

final dataType variableName = value

final 是定义常量的关键字,dataType 指明常量的数据类型,variableName 是变量的名称,value 是初始值。

  • 在定义常量时就需要对该常量进行初始化。
  • final 关键字不仅可以用来修饰基本数据类型的常量,还可以用来修饰对象的引用或者方法。
  • 为了与变量区别,常量取名一般都用大写字符。

# 类型转换

1
2
3
低  ------------------------------------>  高

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

# 强制类型转换

  • 从高到低无损 自动
  • 从低到高有损 手动
  • 强制类型转换
    1. 条件是转换的数据类型必须是兼容的。
    2. 格式:(type) value type 是要强制类型转换后的数据类型
  • 隐含强制类型转换
    1. 小数默认 double float 需要在后面加 f
    2. 整数的默认类型是 int。

# 变量

# 变量分类

  • 类变量:独立于方法之外的变量,用 static 修饰。
  • 实例变量:独立于方法之外的变量,不过没有 static 修饰。
  • 局部变量:类的方法中的变量。

# Java 局部变量

  • 局部变量声明在方法、构造方法或者语句块中;
  • 局部变量在方法、构造方法、或者语句块被执行的时候创建,当它们执行完成后,变量将会被销毁;
  • 访问修饰符不能用于局部变量;
  • 局部变量只在声明它的方法、构造方法或者语句块中可见;
  • 局部变量是在栈上分配的。
  • 局部变量没有默认值,所以局部变量被声明后,必须经过初始化,才可以使用。

# 实例变量

  • 实例变量声明在一个类中,但在方法、构造方法和语句块之外;
  • 当一个对象被实例化之后,每个实例变量的值就跟着确定;
  • 实例变量在对象创建的时候创建,在对象被销毁的时候销毁;
  • 实例变量的值应该至少被一个方法、构造方法或者语句块引用,使得外部能够通过这些方式获取实例变量信息;
  • 实例变量可以声明在使用前或者使用后;
  • 访问修饰符可以修饰实例变量;
  • 实例变量对于类中的方法、构造方法或者语句块是可见的。一般情况下应该把实例变量设为私有。通过使用访问修饰符可以使实例变量对子类可见;
  • 实例变量具有默认值。数值型变量的默认值是 0,布尔型变量的默认值是 false,引用类型变量的默认值是 null。变量的值可以在声明时指定,也可以在构造方法中指定;
  • 实例变量可以直接通过变量名访问。但在静态方法以及其他类中,就应该使用完全限定名:ObjectReference.VariableName。

# 类变量(静态变量)

  • 类变量也称为静态变量,在类中以 static 关键字声明,但必须在方法之外。
  • 无论一个类创建了多少个对象,类只拥有类变量的一份拷贝。
  • 静态变量除了被声明为常量外很少使用,静态变量是指声明为 public/private,final 和 static 类型的变量。静态变量初始化后不可改变。
  • 静态变量储存在静态存储区。经常被声明为常量,很少单独使用 static 声明变量。
  • 静态变量在第一次被访问时创建,在程序结束时销毁。
  • 与实例变量具有相似的可见性。但为了对类的使用者可见,大多数静态变量声明为 public 类型。
  • 默认值和实例变量相似。数值型变量默认值是 0,布尔型默认值是 false,引用类型默认值是 null。变量的值可以在声明的时候指定,也可以在构造方法中指定。此外,静态变量还可以在静态语句块中初始化。
  • 静态变量可以通过:ClassName.VariableName 的方式访问。
  • 类变量被声明为 public static final 类型时,类变量名称一般建议使用大写字母。如果静态变量不是 public 和 final 类型,其命名方式与实例变量以及局部变量的命名方式一致。

# 变量的初始化

  • 类变量 (类静态成员):类被加载时产生;它的生存期是类的生存期;自动初始化 (类被加载)

  • 成员变量 (类成员): 在使用 new 创建该类实例时产生;它的生存期与该类实例对象的生存期相同;

  • 方法中的变量,不会被自动初始化。

# 变量初始化的方法

  • 默认初始化: char c;
  • 显式赋值: char ch = 'x';
  • 调用对象进行初始化赋值: Depth d = new Depth();
  • 调用方法进行初始化赋值: int i = f();

# 数组和字符串的初始化

# 数组
1
2
3
4
5
6
7
8
9
//第一种
int[] is= new int[3];
is[0]=1;
is[1]=2;
is[2]=3;
//第二种
int[] is2= {1,2,3};
//第三种
int[] is3= new int[]{1,2,3};
# 字符串
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
1.直接初始化(字符串常量):在这种方法中,一个String常量对象将被创建在存储器内堆区内的String池中。因为它是一个常量,所以我们不能修改它,即String类是不可变的。
例子:
String str =“GeeksForGeeks”;

str =“geeks”;
//这个声明将使str
//指向新的String常量(“geeks”)
//而不是修改前一个
//字符串常量。
String str =“GeeksForGeeks”;
str =“geeks”;
注意:如果我们再次将str =“GeeksForGeeks”写为下一行,那么它首先检查String String池中是否存在给定的String常量。如果它存在,则str将指向它,否则创建一个新的String常量。

2.对象初始化(动态):在此方法中,将在堆区中创建一个String对象(不在大写字符串池区内)。我们可以对它进行修改。同样的值,在字符串池区也会创建一个String常量,但是这个变量只会指向堆区的String对象。
例子:
String str = new String(“very”);
str =“good”;
String str = new String(“very”)
str =“good”
现在这是一个直接赋值,所以在字符串合并区域中创建带有值“good”的字符串常量,str将指向该字符串。
注意:如果我们再次写入str = new String(“very”),那么它将创建一个值为“very”的新对象,而不是指向堆区中具有相同值的可用对象。但是如果我们写str =“very“,那么它将指向String常量对象,其值为”very“,出现在String池区域中。

# 运算

# 定义

  • 运算
    对常量和变量进行操作的过程称为运算。
  • 运算符
    对常量和变量进行操作的符号称为运算符。
  • 操作数
    参与运算的常量或者变量称为操作数。
  • 表达式
    用运算符把常量或者变量连接起来符合 java 语法的式子就可以称为表达式。
    不同运算符连接的式子体现的是不同类型的表达式。

# 运算符

# 算术运算符

  • 算术运算符用在数学表达式中,它们的作用和在数学中的作用一样。

# 关系运算符

1
== != > < etc.

# 位运算符

操作符 描述 例子
如果相对应位都是 1,则结果为 1,否则为 0 (A&B),得到 12,即 0000 1100
| 如果相对应位都是 0,则结果为 0,否则为 1 (A B)得到 61,即 0011 1101
^ 如果相对应位值相同,则结果为 0,否则为 1 (A ^ B)得到 49,即 0011 0001
按位取反运算符翻转操作数的每一位,即 0 变成 1,1 变成 0。 (〜A)得到 - 61,即 1100 0011
<< 按位左移运算符。左操作数按位左移右操作数指定的位数。 A << 2 得到 240,即 1111 0000
>> 按位右移运算符。左操作数按位右移右操作数指定的位数。 A >> 2 得到 15 即 1111
>>> 按位右移补零操作符。左操作数的值按右操作数指定的位数右移,移动得到的空位以零填充。 A>>>2 得到 15 即 0000 1111

# 逻辑运算符

  • && || !

&& 和 &:
结果一样,但是 && 具有短路效果,左边如果是 false,右边不执行。
|| 和 |:
结果一样,但是 || 具有短路效果,左边如果是 true,右边不执行。

# 赋值运算符

  • = += -= (%)= >>= ^=

# 三目运算符

  • variable x = (expression) ? value if true : value if false

# 函数参数的传递方式

  • 按值传递
    意味着当将一个参数传递给一个函数时,函数接收的是原始值的一个副本。因此,如果函数修改了该参数,仅改变副本,而原始值保持不变。
  • 按引用传递
    意味着当将一个参数传递给一个函数时,函数接收的是原始值的内存地址,而不是值的副本。因此,如果函数修改了该参数,参数的原始值(函数块之外的调用代码中)也随之改变。
    Java 函数参数是按值传递的
    https://www.iteye.com/blog/zzproc-1328591

#

# 定义

类是一种封装机制

# 成员

# 成员分类(配对使用):

  • 属性 / 域、行为 / 方法

# 类的变量

  • 局部变量:在方法、构造方法或者语句块中定义的变量被称为局部变量。变量声明和初始化都是在方法中,方法结束后,变量就会自动销毁。
  • 成员变量:成员变量是定义在类中,方法体之外的变量。这种变量在创建对象的时候实例化。成员变量可以被类中方法、构造方法和特定类的语句块访问。
  • 类变量:类变量也声明在类中,方法体之外,但必须声明为 static 类型。

类成员必定满足以下两个条件之一:

  • 属于整个类型

    成为类变量或者类方法,使用 static 标注

  • 隶属于每个独立的对象或个体

    称之为实例变量或实例方法(实例 = 对象)

# 关系

类可以是独立的,也可以继承,也可以通过接口关联起来

类是一个蓝图,目标是创建类的对象或实例

# 类的创建 declare

  • 修饰符(可选)

    public 修饰访问性 [修饰符]
    abstract 健全性,抽象(不能初始化实例化,即不能创建这个类型的对象,不能在堆里创建这个对象)可以包含抽象方法
    final 最终,不能被子类化,不能作为父类类型
    abstract 与 final 不能共存

  • class 关键字(必须)
  • 标识符(即类型名,必须)
  • extends 子句,用于继承父类
  • implements 子句,用于接口类型
1
2
3
4
5
public class Dog extends Father implements Apible{
String breed;
int size;
void eat() {
}

定义一个类等于定义一个新的数据类型

# 类的 body

constructors 构造器 / 构造方法

  • 类的体要包含至少一个构造器
  • 构造器的方法名和类类型是一样的 new + 构造方法 (构造函数的类型名和类名是一样的)
  • 没有指针,使用 new 申请内存,不需要手动清理无效内存

c:使用时申请 malloc,不使用时释放 free

  • 构造函数不返回任何值
  • 默认构造方法,构造方法没有参数时自动创建。仅在没有写任何构造方法时才有
  • 最好写一个无参的构造方法
  • java 中同一个作用域里不能有同一个标识符,若该标识符为函数名,则可以

函数名+参数类型 + 参数个数才构成一个函数

# 类的 toString 方法

  • 所有类都继承了 Object 的 toString 方法
  • toString 用于类的方法 Object 返回一个字符串,该字符串由对象作为实例的类的名称,符号字符 “@” 和对象的哈希码的无符号十六进制表示组成。

当打印类名自己时,会输出类名和它的地址

  • 可重写该方法,可自定义输出内容。
  1. to String () 方法用途广泛,可以输出数组的内容和类中的属性。
  2. to String () 方法与类使用要重写该方法,可自定义输出内容。
  3. to String () 方法与数组使用时,调用 Arrays 中的 to string()方法。
  4. to String () 方法还可以用于对象数组,使用时既要在类中重写 to String () 方法又要调用 Arrays 类的 to String () 方法。

# 继承

# super 与 this 关键字

  • this 关键字,调用 () 内匹配的构造函数,即重载
  • super 关键字,调用父类类型的构造函数
  • 有 this 不要写 super,但二者都不写也行
  • 都没写的话系统默认加上 super ()
    • 但如果写了任意一个构造方法,系统自动填充的无参构造将不复存在
    • 也就是说,如果父类非空且子类为空,自动填充的 super () 将不会匹配到任何父类构造方法,系统报错
      ### 方法重载与覆盖 overriding/overload
      #### 方法重载 overloading
      在同一个作用域里出现了方法名相同但参数个数以及类型不同
  • 被重载的方法必须改变参数列表 (参数个数或类型不一样);
  • 被重载的方法可以改变返回类型;
  • 被重载的方法可以改变访问修饰符;
  • 被重载的方法可以声明新的或更广的检查异常;
  • 方法能够在同一个类中或者在一个子类中被重载。
  • 无法以返回值类型作为重载函数的区分标准。

#### 方法覆盖 overriding

重写是子类对父类的允许访问的方法的实现过程进行重新编写,返回值和形参都不能改变。即外壳不变,核心重写!

  • 发生在两个不同作用域,继承关系中

  • 参数列表与被重写方法的参数列表必须完全相同。

  • 返回类型与被重写方法的返回类型可以不相同,但是必须是父类返回值的派生类(java5 及更早版本返回类型要一样,java7 及更高版本可以不同)。

  • 访问权限不能比父类中被重写的方法的访问权限更低。例如:如果父类的一个方法被声明为 public,那么在子类中重写该方法就不能声明为 protected。

  • 父类的成员方法只能被它的子类重写。

  • 声明为 final 的方法不能被重写。

  • 声明为 static 的方法不能被重写,但是能够被再次声明。

  • 子类和父类在同一个包中,那么子类可以重写父类所有方法,除了声明为 private 和 final 的方法。

  • 子类和父类不在同一个包中,那么子类只能够重写父类的声明为 public 和 protected 的非 final 方法。

  • 重写的方法能够抛出任何非强制异常,无论被重写的方法是否抛出异常。但是,重写的方法不能抛出新的强制性异常,或者比被重写方法声明的更广泛的强制性异常,反之则可以。

  • 构造方法不能被重写。

  • 如果不能继承一个类,则不能重写该类的方法。

  • 当需要在子类中调用父类的被重写方法时,要使用 super 关键字。

重写的好处在于子类可以根据需要,定义特定于自己的行为。 也就是说子类能够根据需要实现父类的方法。
###main 方法
public static void main (String [] xxx){}
### 封装 encapsulation
使用 private 修饰,保护本方法。若要外界访问需要设定相对应的 public 成员方法。
### 访问修饰符 Access modifiers
例题 1
例题 2

  • private 受限到当前类中
  • default (什么修饰符都不要用)受限于包
  • protected 受限于当前包,但可以被这个类的所有子类访问子类实例可以访问其从基类继承而来的 protected 方法而不能访问基类实例的 protected 方法
  • public 都可以

子类继承但不一定能访问父类的数据成员和成员方法,还受到访问修饰符限制

# 非访问修饰符

# static 修饰符

  • 静态域和方法都属于这个类,域只有一份拷贝
  • 可以不实例化类而接入
  • 使用 static 声明
  • 声明独立于对象的静态方法,静态方法不能使用类的非静态变量。

# final 修饰符

  • final 变量不可被修改
  • final 方法可以被继承但不能被子类重写

使用 final static 定义常量

# abstract 修饰符

  • 不可被实例化

  • 没有实现体

  • 一个类若有抽象方法就必须是抽象类,但可以有实例方法
    ### 包 package
    例题 3
    例题 4

  • 物理上对应文件夹 (包名全小写)

  • 全称的定义:包名。类型

  • 包只会物理上包含但逻辑上不包含,如下解释

### 类的可见性

  • 在同一个包中互相可见
  • 不在一个包借助包名可见
  • 使用 import 导入,可以导入一个类,或使用.* 导入所有类
    ### 类的层次 Class hierarchies

instantiates->Interger->Number->Object

  • Object 是整个层次的根类
    ### 特殊化与泛化 Specialization and generalization
    子类是父类的特殊化,父类是子类的泛化
    ### 继承关系 Inheritance ralationships
    继承 is a 关系,但不能描述成 has a 关系(has 指部分和整体)
    子类继承父类的域和方法

### 方法覆盖 overriding methods
在子类中使用同签名方法替代父类的

  • 参数以及名字一定要匹配(否则就是重载)
  • 子类的访问修饰符不能比父类更严格
    编译阶段参照变量类型进行判断而不是依赖变量所指对象的类型
    ### 继承例题
    #### 例题一
    Given the following classes and declarations, which statements are true? //Classes
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Foo{ 
private int i;
public void f(){/*..*/}
public void g() { /* .. */} }

class Bar extends Foo {
public int j;
public void g(){/*...*/}
}
//Declarations:
Foo a = new Foo();
Bar b = new Bar();
Foo c = b;
//此处可以父类指向子类,但不能反着来

#### 例题二

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Vehicle{
static public String getModelName() { return "Volvo"; }
public long getRegNo() { return 12345; }
}

class Car extends Vehicle {
static public String getModelName() { return "Toyota"; }
public long getRegNo() { return 54321;}
}

public class TakeARide {
public static void main(String args\[\]){ Car c = new Car();
Vehicle v=c;
System.out.print1n("|" + v.getMode1Name() +"|"+ c.getMode1Name()+
"|" + v.getRegNo() +"|"+ c.getRegNo() +"|");
}

答案:

  1. volvo
  2. toyota
  3. 54321
  4. 54321

#### 例题三

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
Package One{
Class Alpha{
private int a;
int b;
protected int c;
public int d;
}
Class Beta{
Alpha obj=new Alpha();
obj.a++; //F
obj.b++; //T
obj.c++; //T
obj.d++; //T
}
}
Package Two{
Class AlphaSub extends One.Alpha{
Alpha obj=new Alpha();
obj.a++; //F
obj.b++; //F
obj.c++; //F
obj.d++; //T
a++; //F
b++; //F
c++; //T
d++; //T
}
Class Gamma{
Alpha obj=new Alpha();
obj.a++; //F
obj.b++; //F
obj.c++; //F
obj.d++; //T
}
}

#### 例题四

1
2
3
4
5
6
7
8
9
import xjtu.*//只会调用前俩,不会调用se,大括号代表文件夹
xjtu{
a.java
b.java
se{
a.java
b.java
}
}
表格 hiding overriding 编译阶段(静态) 运行阶段
数据成员 检查语法并确定成分对象 按编译结果直接执行
成员方法 - 类方法 (static) 检查语法并确定成分对象 按照编译结果直接执行
成员方法 - 实例方法 检查语法 按照调用方法的对象的实际类型来选择方法执行
super.method() × 检查语法并确定成分对象 按照编译结果直接执行

# 接口 interface

# 接口与类

  • java 中被声明的要么是类要么是接口(接口不是类,绝不是继承关系
  • 创建的关键字为 interface
  • 接口里的方法不能被实例化 (implement)
  • 定义接口目的是让类类型去实现接口定义的没有被实现的方法,是一种由对象去实现的合同 (contract)

抽象类能有实例化的成员,但接口不可以
抽象类成员变量可以是各种类型,但接口只是 public static final

  • 接口中不能有静态代码块以及静态方法,但抽象类可以
  • 接口支持多继承,但类不可以
  • 接口不是被类继承了,是被类实现
  • 接口中的方法隐式指定为 public abstract

# 接口命名

  • 使用 able 结尾
  • 接口命名为单词,实现接口的类命名为接口名 + Impl
  • 在名词前面加上 I 表示接口

# 接口声明与实现

  • A 实现 File 接口,B 为 A 子类,B 自动拥有 A 对 File 的实现,且实现方法可以 overriding

Cloneable 接口不包含任何方法,作为标记接口,标记接口可以作为一组接口的父接口,也可以向一个类添加数据类型

1
2
3
File r=new File() //error
File f=new TextFile()//ok,TextFile是实现了File接口的一个对象
//f只能调用File内的方法,调用的是TextFile内的方法
  • 接口之间也可以被 extends

[可见度] interface 接口名字 extends 其他接口名 {
// 声明变量
// 抽象方法
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
interface File{
public void open();
public void close();//2个
}
interface Read extends File{
public byte readByte();//3个
}
interface Write extends File{
public void writeByte(byte b);//3个
}
interface ReadWrite extends Read,Writr{
public void seek(int pos);//5个
}

public class Directory extends Secure implements File,Secure{
...
}

## 多态 polymorphism
### 定义

  • 多态就是同一个行为具有不同的表现形式或能力
  • 多态是同一个接口使用不同的实例执行不同的操作
    ### 多态存在的三个必要条件
  1. 继承
  2. 重写
  3. 父类引用指向子类对象: Parent p= new Child();
    ### 实现方式
  4. 重写 overriding
  5. 接口 interface
  6. 抽象类和抽象方法 abstract
    ### 跨层多态 cross-hierarchy polymorphism
    接口允许不同的继承树借助同一个接口访问同一个方法
    提高了代码的可复用性

# 例外 Exception

# 定义

  • 是一种事件或者条件,阻止程序正常执行

# 分类

  • 检查性异常:最具代表的检查性异常是用户错误或问题引起的异常,这是程序员无法预见的。例如要打开一个不存在文件时,一个异常就发生了,这些异常在编译时不能被简单地忽略。
  • 运行时异常: 运行时异常是可能被程序员避免的异常。与检查性异常相反,运行时异常可以在编译时被忽略。
  • 错误: 错误不是异常,而是脱离程序员控制的问题。错误在代码中通常被忽略。例如,当栈溢出时,一个错误就发生了,它们在编译也检查不到的。

# 特点

  • 是一种错误
  • java 处理方式是抛出一个例外
  • 整个例外的控制是由 catch/try/final 语句组合来完成
  • 使用 try/catch/finally 语句块处理例外,handle 处理器
  • throw/throws 表现对例外的处理态度
  • 当一个方法产生例外后,当这个例外在这个方法中没有被处理,这个例外会沿着调用栈的顺序依次传播出去,直到调用栈的某一个方法对这个例外进行了处理

# 关键字

# try/catch

  • 使用 try 和 catch 关键字可以捕获异常。try/catch 代码块放在异常可能发生的地方。
  • catch 的顺序很重要,因为是从上到下匹配的,匹配后直接结束。
1
2
3
4
5
6
7
8
9
10
11
try {
file = new FileInputStream(fileName);
x = (byte) file.read();
} catch(FileNotFoundException f) { // Not valid!
f.printStackTrace();
return -1;
} catch(IOException i) {
i.printStackTrace();
return -1;
}

# throws/throw

  • 如果一个方法没有捕获到一个检查性异常,那么该方法必须使用 throws 关键字来声明。throws 关键字放在方法签名的尾部。
  • 也可以使用 throw 关键字抛出一个异常,无论它是新实例化的还是刚捕获到的。(主动抛出)
  • 抛出异常若没有被处理则会一直逐层向上抛出直至 JVM
    ####finally
  • finally 关键字用来创建在 try 代码块后面执行的代码块。
    无论是否发生异常,finally 代码块中的代码总会被执行。

try, catch, finally 块之间不能添加任何代码:

  • 当不存在 catch 语句时,finally 语句必须存在并且紧跟在 try 语句后面。
  • 在 try 语句和 catch 语句间不能存在任何语句,同样在 catch 语句和 finally 语句中也不能存在任何语句,这地方的语句不包括注释语句。
  • 当不存在 catch 语句时,finally 语句必须存在并且紧跟在 try 语句后面。在 try 语句和 catch 语句间不能存在任何语句。

# 自定义异常

  • 所有异常都必须是 Throwable 的子类。
  • 如果希望写一个检查性异常类,则需要继承 Exception 类。
  • 如果你想写一个运行时异常类,那么需要继承 RuntimeException 类。
  • 方法:自定义异常类型 -> 写一个可能抛出异常的方法 -> 调用该方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
public class MyException extends Exception//自定义异常类型
{
public MyException()
{}
public MyException(String s)
{
super(s);
}
}
public class ExceptionClass//写一个可能抛出异常的方法
{
public String setNumber(int number) throws MyException
{
if(number >= 0 && number <=100)
{
return "正常";
}
else
{
throw new MyException("输入错误");
}
}

}
public class MainClass
{
public static void main (String args[])
{
try{
ExceptionClass exception = new ExceptionClass();//调用该方法
String s = exception.setNumber(90);
System.out.println(s);
}
catch(MyException e)
{
System.out.println("异常信息为:"+e.getMessage());
}
}
}


# 流控制

# if-else

  • 一个 if 语句包含一个布尔表达式和一条或多条语句。
  • if 语句后面可以跟 else 语句,当 if 语句的布尔表达式值为 false 时,else 语句块会被执行。
  • if 语句后面可以跟 else if…else 语句,这种语句可以检测到多种可能的情况。
    使用 if,else if,else 语句的时候,需要注意下面几点:
    1. if 语句至多有 1 个 else 语句,else 语句在所有的 else if 语句之后。
    2. if 语句可以有若干个 else if 语句,它们必须在 else 语句之前。
    3. 一旦其中一个 else if 语句检测为 true,其他的 else if 以及 else 语句都将跳过执行。

# switch case

# switch 语法

1
2
3
4
5
6
7
8
9
10
11
switch(expression){
case value :
//语句
break; //可选
case value :
//语句
break; //可选
//你可以有任意数量的case语句
default : //可选
//语句
}
  • switch 语句中的变量类型可以是: byte、short、int 或者 char。从 Java SE 7 开始,switch 支持字符串 String 类型了,同时 case 标签必须为字符串常量或字面量。

  • switch 语句可以拥有多个 case 语句。每个 case 后面跟一个要比较的值和冒号。

  • case 语句中的值的数据类型必须与变量的数据类型相同,而且只能是常量或者字面常量。

  • 当变量的值与 case 语句的值相等时,那么 case 语句之后的语句开始执行,直到 break 语 - 句出现才会跳出 switch 语句。

  • 当遇到 break 语句时,switch 语句终止。程序跳转到 switch 语句后面的语句执行。

    case 语句不必须要包含 break 语句。如果没有 break 语句出现,程序会继续执行下一条 case 语句,直到出现 break 语句。

  • switch 语句可以包含一个 default 分支,该分支一般是 switch 语句的最后一个分支(可以在任何位置,但建议在最后一个)。default 在没有 case 语句的值和变量值相等的时候执行。default 分支不需要 break 语句。

  • switch case 执行时,一定会先进行匹配,匹配成功返回当前 case 的值,再根据是否有 break,判断是否继续输出,或是跳出判断。

# 循环

# 循环结构

  • Java 中有三种主要的循环结构:
    1. while 循环
    2. do…while 循环
    3. for 循环

    对于 do…while,布尔表达式在循环体的后面,所以语句块在检测布尔表达式之前已经执行了,即至少执行一次。 如果布尔表达式的值为 true,则语句块一直执行,直到布尔表达式的值为 false。

# break 关键字

  • break 主要用在循环语句或者 switch 语句中,用来跳出整个语句块。

  • break 跳出最里层的循环,并且继续执行该循环下面的语句。

# continue 关键字

  • continue 适用于任何循环控制结构中。作用是让程序立刻跳转到下一次循环的迭代。

  • 在 for 循环中,continue 语句使程序立即跳转到更新语句。

  • 在 while 或者 do…while 循环中,程序立即跳转到布尔表达式的判断语句。

# 标签

  • 在 JAVA 中,标签是后面带有冒号的标识符 outer:
  • break 和 continue 关键词通常只中断当前循环,但若随同标签一起使用,它们就会中断循环,直到标签所在的地方:

流控制例题

更新于 阅读次数

请我喝[茶]~( ̄▽ ̄)~*

小春日和 微信支付

微信支付

小春日和 支付宝

支付宝

小春日和 wechat

wechat