JavaSE基础
oop:面上对象
强类型语言
Debug
常见Dos命令
E: 盘符切换
dir 查看当前目录下文件
cd.. 返回上一级
cls
exit
ipconfig 查看电脑IP
#打开应用
calc 打开计算器
mapaint 打开画图
notepad 新建记事本
ping www.baidu.com
#文件操作
md 目录名
rd 目录名 删除目录
cd>文件名 新建文件
del 文件名
机器语言→汇编语言→高级语言(面向过程&面向对象)
简单性、面向对象、可移植性、高性能、分布式、动态性、多线程、安全性、健壮性
编译型&解释型
基本语法
注释
// 单行注释
/*
多行注释
*/
/**
*@Author
*/ Javadoc:文档注释
/***
* _ooOoo_
* o8888888o
* 88" . "88
* (| -_- |)
* O\ = /O
* ____/`---'\____
* . ' \\| |// `.
* / \\||| : |||// \
* / _||||| -:- |||||- \
* | | \\\ - /// | |
* | \_| ''\---/'' | |
* \ .-\__ `-` ___/-. /
* ___`. .' /--.--\ `. . __
* ."" '< `.___\_<|>_/___.' >'"".
* | | : `- \`.;`\ _ /`;.`/ - ` : | |
* \ \ `-. \_ __\ /__ _/ .-` / /
* ======`-.____`-.___\_____/___.-`____.-'======
* `=---='
*
* .............................................
* 佛祖保佑 永无BUG
*/ 有趣代码等等
标识符
Java所有组成部分都需要名字。类名,变量名以及方法名被称为标识符
只能以字母、美元符&、和下划线_开始;不能使用关键字命名
标识符大小写敏感—强类型语言,不建议使用中文
数据类型
基本类型(primitive type)&引用类型(reference type)
Java数据类型
├─ 基本数据类型(原生类型 8种)
│ ├─ 整数型
│ │ ├─ byte:1字节,范围 -128 ~ 127
│ │ ├─ short:2字节,范围 -32768 ~ 32767
│ │ ├─ int:4字节,范围 -2147483648 ~ 2147483647
│ │ └─ long:8字节,范围 -9223372036854775808 ~ 9223372036854775807
│ ├─ 浮点型
│ │ ├─ float:4字节,单精度浮点数
│ │ └─ double:8字节,双精度浮点数(默认)
│ ├─ 字符型
│ │ └─ char:2字节,'\u0000' ~ '\uFFFF'
│ └─ 布尔型
│ └─ boolean:1bit,取值 true / false
└─ 引用数据类型
├─ 类(Class)
├─ 接口(Interface)
├─ 数组(Array)
├─ 枚举(Enum)
└─ 注解(Annotation)
进制
二进制0b 十进制 八进制0 十六进制0x
银行业务该怎么表示?
最好完全避免使用浮点数进行比较:字节有限、离散、舍入误差、大约、接近但不等于;用数学工具类BigDecimal表示
字符拓展
强制转换:所有的字符本质还是数字
编码 Unicode 2字节 0—$2^{16}$/65536
| 转义字符 | 含义 | 作用说明 |
|---|---|---|
\n |
换行 | 光标跳到下一行开头 |
\t |
制表符 | 相当于按 Tab 键,缩进对齐 |
\r |
回车 | 光标回到本行开头 |
\b |
退格 | 光标后退一格,删除前一个字符 |
\' |
单引号 | 输出单个 ' |
\" |
双引号 | 输出单个 " |
\\ |
反斜杠 | 输出单个 \ |
\f |
换页符 | |
\u0061 |
Unicode转义字符 | 输出a |
内存分析
定义对象的时候,同名的对象并不等于完全相同,重现new空间,比较的是内存地址,而地址不同
布尔值扩展
Less is More!代码要精简
类型转换
强制类型转换、内存溢出
低————————————————>高
byte,short,char->int->long->float->double
- 不能对布尔值进行转换
- 不能把对象类型转换为不相干的类型
- 把高容量转换到底容量时要强制转换,需要主义内存溢出;低转换成高时自动转换
- 存在内存溢出,或者精度问题
变量
变量名&变量类型&作用域
- 每个变量都有类型,可以是基本类型,也可以是引用类型
- 变量名必须是合法的标识符
- 变量声明都是一条完整的语句,每一个声明都必须以分号结束
public class Variable {
static int a = 1; //类变量
String str = "Hello World"; //实例变量
public void method(){
int i = 2; //局部变量
}
}
局部变量:处于方法内部,必须声明和初始化值
实例变量:方法外部类里面,从属于对象;如果不进行初始化,是这个类的默认值
类变量:前有 static
常量
初始化后不在改变的值,前有关键字final
final double PI = 3.14;
修饰符,不区分先后顺序
命名规范
- 所有变量、方法名、类名:见名知意
- 类成员变量:首字母小写&驼峰原则:mouthSalary、lastName……
- 局部变量:首字母小写&驼峰原则
- 常量:大写字母和下划线:MAX_VALUE……
- 类名:首字母大写&驼峰原则:Man、GoodMan……
- 方法名:首字母小写&驼峰原则:run()、runRun()……
运算符
- 算数运算符:+,-,*,/,%,++, - -
- 赋值运算符:=
- 关系运算符:>,<,>=,<=,==,!=,instanceof
- 逻辑运算符:&&,||,!
- 位运算符:&,|,^,~,>>,<<,>>>
- 条件运算符:?:
- 扩展赋值运算符:+=,-=,*=,/=
Ctrl + D:复制当前行到下一行
幂运算
double pow = Math.pow(2, 3);
System.out.println(pow);
很多运算会使用一些工具类来实现
逻辑运算
与&&,或||,非!
短路运算
//短路运算
int c = 5;
boolean d = (c<4)&&(c++<4);
System.out.println(d); //false
System.out.println(c); //c = 5
位运算
/*
A = 0011 1100
B = 0000 1101
-----------------
A&B = 0000 1100
A|B = 0011 1101
A^B = 0011 0001 //异或:相同取0,不同取1
~A = 1100 0011
-----------------
<< *2
>> /2
*/
System.out.println(2 << 3); //2<<3 = 16
字符串连接符 +
int a = 10;
int b = 20;
System.out.println(a + b);
System.out.println(a + b + "hello"); //30hello
System.out.println("hello" + a + b); //hello1020
三元运算符 ? :
int score = 80;
String result = score < 60 ? "不及格" : "及格";
System.out.println(result); //及格
JavaDoc
javadoc -encoding UTF-8 -charset UTF-8 Doc.java //在Dos窗口执行,打开index.html文件
使用IDEA生产JavaDoc文档
面向百度编程!
流程控制
Scanner对象
通过Scanner类的next()和nextLine()方法获取输入的字符串,需要使用hasNext()和hasNextLine()先判断是否还有输入的数据,最后省资源需要有scanner.close()
next()
1.一定要读取有效字符后才结束输入
2.对输入字符之前遇到空白,next()会自动将其去掉
3.只有输入有效字符后,其后面的空白作为分隔符or结束符
4.next()不能得到带有空格的字符串⭐
nextLine()
1.以Enter为结束符,返回回车前的所有字符
2.可以获取空白
输入多个数字,求其总和和平均数
import java.util.Scanner;
public class average {
public static void main(String[] args) {
//可以输入多个数字,并求其总和和平均数,每输入一个数字回车确认,通过非数字来结束平输出执行结果
Scanner scanner = new Scanner(System.in);
//和
double sum = 0;
//计算输入的数字个数
int m = 0;
System.out.println("请输入数据:");
//判断用户有没有输入数据,并在里面进行求和统计
while (scanner.hasNextDouble()) {
double x = scanner.nextDouble();
m++;
sum += x;
}
System.out.println(m + "个数字总和为" + sum);
System.out.println(m + "个数字平均值为" + sum / m);
scanner.close();
}
}
顺序结构
若干个依次执行的处理步骤组成,任何一种算法都离不开的基本算法结构
选择结构
if 单选结构、if 双选择结构、if 多选择结构、嵌套的 if 结构
if 多选择结构注意事项
if 语句中至多有一个 else 语句,else 语句在所有的 else if 语句之后
if 语句可以有若干个 else if 语句,他们必须在 else 语句之前
一旦一个 else if 检测到 true ,其他 else if && else 跳过执行
import java.util.Scanner;
public class Order {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入内容");
String s = scanner.nextLine();
if (s.equals("hello")) {
System.out.println(s);
}
System.out.println("End");
System.out.println("请输入成绩");
int score = scanner.nextInt();
if (score > 60) {
System.out.println("及格");
} else {
System.out.println("不及格");
}
scanner.close();
}
}
Switch 多选择结构
-
判断变量与系列分支中的某个值是否相等,每个值称为一个分支
-
Switch匹配一个具体的值
-
从Java SE7 开始,Switch支持字符串String类型
-
同时case标签必须为字符串常量和字面量
case穿透现象
反编译
循环结构
while循环
while(布尔表达式){
//循环内容
}
- 布尔表达式为true,循环就一直执行下去
- 大多数情况下需要让循环停下来,需要一种表达式失效方式
- 少数情况下一直循环,比如服务器的请求响应监听等
- 死循环
do…while循环
while语句如果不满足条件,则不能进入循环
do…while至少会执行一次
do{
//代码语句
}while(布尔表达式);
for循环
for(初始化;布尔表达式;更新){
//代码语句
}
- for循环是一种支持迭代的通用结构,最有效、最灵活的循环结构
- for循环次数在执行前就确定的
最先执行初始化步骤,可以声明一种类型,可以初始化一个或多个循环控制变量,也可以是空语句
然后检测布尔表达式的值,true执行循环体
执行循环后,更新循环控制变量(迭代因子控制循环变量的增减)
再次检测布尔表达式的值,循环执行上面过程
计算0到100之间的奇数和偶数和
public static void main(String[] args) {
//计算0到100之间的奇数和偶数和
int oddSum = 0;
int evenSum = 0;
for (int i = 0; i < 100; i++) {
if (i % 2 == 0) { //偶数
evenSum += i;
} else { //奇数
oddSum += i;
}
}
System.out.println("奇数的和:" + oddSum);
System.out.println("偶数的和:" + evenSum);
}
用while或者for循环输出1-1000之间能被5整除的数,每行输出3个
public static void main(String[] args) {
//用while或者for循环输出1-1000之间能被5整除的数,每行输出3个
for (int i = 1; i <= 1000; i++) {
if(i % 5 == 0) { //判断是否能被5整除
System.out.print(i + "\t");
}
if (i % (5*3) ==0){ //每行3个
System.out.println();
}
//println 输出完换行
//print 输出完不换行
}
}
打印九九乘法表
public static void main(String[] args) {
//九九乘法表
for (int i = 1; i <= 9; i++) {
for (int j = 1; j <= i; j++) {
System.out.print(j + "*" + i + "=" + i * j + "\t");
}
System.out.println();
}
}
增强for循环
for(声明语句:表达式)
{
//代码句子
}
- Java5 引入主要用于数组和集合的增强for循环
- 声明语句:声明新的局部变量,类型与数组元素匹配,作用域限定在循环语句块
- 表达式:表达式是要访问的数组名,或者返回值为数组的方法
break、continue
break:用于循环语句的主体部分,用于强行退出循环,不执行剩余语句
continue:用于循环体语句中,终止某次循环过程;跳过未执行语句,接着进行下一次是否执行循环的判定
goto关键字
保留goto关键字,Java中用标签lebal+continue跳到指定循环语句,一般也不常用
打印三角形
public static void main(String[] args) {
// 打印三角形
for (int i = 1; i <= 5; i++) {
for (int j = 5; j >= i; j--) {
System.out.print(" ");
}
for (int j = 1; j <= i; j++) {
System.out.print("*");
}
for (int j = 1; j < i; j++) {
System.out.print("*");
}
System.out.println();
}
}
Java方法
修饰符 返回值类型 方法名(参数类型 参数名){
...
方法体
...
return 返回值;
}
- 方法是语句的集合,能够执行一个功能,功能块
- 方法是解决一类问题的的步骤有序组合
- 方法包含于类或者对象中
- 方法在程序中创建,在其他地方被引用
- 设计方法保持原子性,一个方法只能完成一个功能,有利于后期的扩展
- Java中的方法相当于其他语言中的函数
方法调用
方法调用通常被当做一个值
当返回值为void值,方法调用一定是一条语句
//比大小
public static int max ( int a, int b){
int result = 0;
if (a == b) {
System.out.println("相等");
return 0;
}
if (a > b) {
result = a;
} else {
result = b;
}
return result;
}
值传递&引用传递
java都是值传递
方法重载
- 方法重载在同一个类中,有相同的函数名称,但形参不同
- 规则
- 方法名必须相同
- 参数列表必须不同(个数,类型,参数排列顺序)
- 返回类型可以相同也可以不同
- 仅返回类型不同不足以称为方法的重载
- 方法名相同时,编译器会根据调用方法的参数个数,参数类型去逐个匹配,以选择对应方法,匹配失败则报错
可变参数
- jdk1.5开始,Java支持传递同类型的可变参数
- 在方法声明中,在指定参数类型后加一个省略号…
- 一个方法中只能有一个可变参数,必须是方法的最后一个参数,任何普通参数必须在它声明之前
public static void main(String[] args) {
printMax(1, 2, 3, 4, 5);
printMax(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
printMax();
}
public static void printMax (double... nums){
if (nums.length == 0){
System.out.println("No arguments passed");
return;
}
double max = nums[0];
for (int i = 1; i < nums.length; i++){
if (nums[i] > max){
max = nums[i];
}
}
System.out.println("The max value is " + max);
}
递归
- 自己调用自己
- 结构
- 递归头:什么时候不调用自身方法
- 递归体:什么时候需要调用自身方法
边界条件、前阶段、返回阶段
public static void main(String[] args) {
System.out.println(f(5));
}
public static int f(int n){
if (n == 1){
return 1;
}
return n * f(n - 1);
}
尽量避免使用递归
加减乘除计算器
import java.util.Scanner;
public class Calculator {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("=== Java 计算器 ===");
System.out.println("运算: +, -, *, / | 输入 q 退出");
while (true) {
System.out.print("\n输入第一个数字 (q退出): ");
String input = scanner.next().trim();
if (input.equalsIgnoreCase("q")) {
System.out.println("再见!");
break;
}
double num1;
try {
num1 = Double.parseDouble(input);
} catch (NumberFormatException e) {
System.out.println("无效数字!");
continue;
}
System.out.print("输入运算符: ");
char op = scanner.next().charAt(0);
if ("+-*/".indexOf(op) == -1) {
System.out.println("无效运算符!");
continue;
}
System.out.print("输入第二个数字: ");
double num2;
try {
num2 = scanner.nextDouble();
} catch (Exception e) {
System.out.println("无效数字!");
scanner.next();
continue;
}
try {
double result = 0;
switch (op) {
case '+': result = num1 + num2; break;
case '-': result = num1 - num2; break;
case '*': result = num1 * num2; break;
case '/':
if (num2 == 0) throw new ArithmeticException("除数不能为零");
result = num1 / num2;
break;
}
System.out.printf("结果: %.2f %c %.2f = %.2f\n", num1, op, num2, result);
} catch (ArithmeticException e) {
System.out.println("错误: " + e.getMessage());
}
System.out.print("继续计算?(y/n): ");
if (!scanner.next().equalsIgnoreCase("y")) {
System.out.println("再见!");
break;
}
}
scanner.close();
}
}
数组
- 数组是相同类型数据的组合
- 若干个同类型数据排列组合而成
- 每一个数据称作数据元素,每一个元素可以通过下标来访问
数组的声明和创建
dataType[] arrayRefVar; //命名
dataType[] arrayRefVar = new dataType[arraySize]; //创建新数组
- 数组的元素是通过索引来访问的,索引从0 开始
- arrays.length或缺数组长度
- 数组的长度是固定的
- 数据元素必须为相同类型的有序集合,可以为任何类型
- 数组变量属引用类型,数组也可看作是对象,每个元素相当于该对象的成员变量
- 数组对象本身是在堆中的
三种初始化及内存分析
-
静态初始化
int[] a = {1,2,3}; Man[] mans = {new Man(1,1),new Man(2,2)}; -
动态初始化
int[] = new int[2]; a[0] = 1; a[1] = 2; -
默认初始化
- 数组是引用类型,它的元素相当于类的实例变量,一经分配空间,每一个元素按照实例变量同样的方式被隐式初始化
数组下标越界异常
Array Index Out Of Bounds Exception
数组的使用
For-Each 循环
public static void main(String[] args) {
int[] array = {1,2,3,4,5,6,7,8,9,10};
//打印全部数组元素
for (int i = 0; i < array.length; i++) {
System.out.println(array[i]);
}
//求和
int sum = 0;
for (int i = 0; i < array.length; i++) {
sum += array[i];
}
System.out.println("sum=" + sum);
//求最大值
int max = array[0];
for (int i = 0; i < array.length; i++) {
if (array[i] > max) {
max = array[i];
}
}
System.out.println("max=" + max);
}
数组作方法入参&数组作为返回值
public static void main(String[] args) {
int[] arrays = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
//for (int array : arrays) {
// System.out.println(array);
//} For增强
printArray(arrays);
System.out.println(" ");
int[] reverse = reverse(arrays);
printArray(reverse);
}
//打印数组
public static void printArray(int[] array) {
for (int i = 0; i < array.length; i++)
System.out.print(array[i] + " ");
}
//反转数组
public static int[] reverse(int[] array) {
int[] result = new int[array.length];
for (int i = 0, j = result.length - 1; i < array.length; i++, j--) {
result[j] = array[i];
}
return result;
}
多维数组
public static void main(String[] args) {
//二维数组
int[][] arr = {{1,2,3},{4,5,6},{7,8,9}};
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr[i].length; j++)
System.out.print(arr[i][j]+" ");
}
}
//打印数组
public static void printArray(int[] array) {
for (int i = 0; i < array.length; i++)
System.out.print(array[i] + " ");
}
Arrays类讲解
学会查源码,调用方法
- 给数组赋值:通过 fill 方法
- 给数组排序:通过 sort 方法升序
- 对比数组:通过 equals 方法比较数组元素是否相等
- 查找数组元素:通过 binarySearch 方法对排序的数组进行二分查找法操作
冒泡排序
八大排序
public static void main(String[] args) {
int[] array = {1,28,36,43,75,61,17,8,9};
System.out.println(Arrays.toString(sort(array)));
}
//冒泡排序
public static int[] sort(int[] array){
//临时变量
int temp = 0;
//外层循环
for (int i = 0; i < array.length-1; i++) {
//内层循环
for (int j = 0; j < array.length-1-i; j++) {
if (array[j] > array[j+1]) {
temp = array[j];
array[j] = array[j+1];
array[j+1] = temp;
}
}
}
return array;
}
冒泡排序两层循环,外层魔炮轮数,里层依次比较;嵌套循环,时间复杂度为$O(n^2)$
如何优化冒泡排序
boolean flag == false;
稀疏数组
输出原始的数组
0 0 0 0 0 0 0 0 0 0 0
0 0 1 0 0 0 0 0 0 0 0
0 0 0 2 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
========================
有效数据个数=2
稀疏数组
11 11 2
1 2 1
2 3 2
public static void main(String[] args) {
//创建一个11*11数组
int[][] array1 = new int[11][11];
array1[1][2] = 1;
array1[2][3] = 2;
//输出原始数组
System.out.println("输出原始的数组");
for (int[] ints : array1) {
for (int anInt : ints) {
System.out.print(anInt+"\t");
}
System.out.println();
}
System.out.println("========================");
//转换稀疏数组保存
//1.获取原始数组中有效数据的个数
int sum = 0;
for (int i = 0; i < array1.length; i++) {
for (int j = 0; j < array1[i].length; j++) {
if (array1[i][j] != 0) {
sum++;
}
}
}
System.out.println("有效数据个数="+sum);
//2.创建一个稀疏数组
int[][] array2 = new int[sum+1][3];
array2[0][0] = 11;
array2[0][1] = 11;
array2[0][2] = sum;
//3.遍历原始数组,将非0的值存放到稀疏数组中
int count = 0;
for (int i = 0; i < array1.length; i++) {
for (int j = 0; j < array1[i].length; j++) {
if (array1[i][j] != 0) {
count++;
array2[count][0] = i;
array2[count][1] = j;
array2[count][2] = array1[i][j];
}
}
}
//输出稀疏数组
System.out.println("稀疏数组");
for (int[] ints : array2) {
for (int anInt : ints) {
System.out.print(anInt + "\t");
}
System.out.println();
}
//还原原始数组
System.out.println("========================");
System.out.println("还原原始数组");
int[][] array3 = new int[array2[0][0]][array2[0][1]];
for (int i = 1; i < array2.length; i++) {
array3[array2[i][0]][array2[i][1]] = array2[i][2];
}
System.out.println("输出原来的数组");
for (int[] ints : array3) {
for (int anInt : ints){
System.out.print(anInt + "\t");
}
System.out.println();
}
}
面向对象编程
面向过程是线性的,面向对象的分类的;面向对象适合处理复杂的问题,适合多人协作。
从宏观上把握,从整体上合理分析,需要使用面向对象来分析整个系统;但是具体到微观操作,仍然需要面向过程的思路去处理。
以类的方式组织代码,以对象的方式组织(封装)数据
封装、继承、多态
静态方法是和类一起加载的,非静态方法必须实例化后才存在
实际参数和形式参数的类型要对应
值传递&引用传递
类和对象的关系
类是抽象的数据类型
对象是抽象概念的具体实例
创建和初始化对象
-
使用 new 关键字创建对象
- 创建对象除了分配空间之外,还会进行默认的初始化以及构造及器的调用
- 类中的构造器也称构造方法
- 必须和类的名字相同
- 必须没有返回类型,也不能写 void
构造器必须要掌握
Alt + Fn + insert 快捷键生成构造器
封装
- 高内聚,低耦合:类的内部数据操作细节由自己完成,不允许外部干涉;仅暴露少量的方法给外部使用
- 封装(数据的隐藏):禁止直接访问一个对象中数据的实际表示,应通过操作接口来访问,称为信息隐藏
- 属性私有,get/set
- 提高程序的安全性,保护数据
- 隐藏代码的实现细节
- 统一接口
- 提高系统的可维护性
继承
- 继承的本质是对某一批类的抽象;java中只有单继承,没有多继承
- extends 的意思是扩展,子类是父类的扩展
- 继承是类和类之间的关系,除此之外,还有依赖、组合、聚合等
- 子类(派生类),父类(基类),使用关键字extends来联系
- “is a”的关系
public & private & default & protected
Ctrl + H 查看继承树
java 中,所有的类都默认继承 object 类
super注意点:
1. super调用父类的构造方法,必须在子类构造方法的第一行
2. super必须只能出现在子类的方法或者构造方法中
3. super和this不能同时调用构造方法!
VS this:
代表的对象不同:
this:本身调用者这个对象
super:代表父类对象的应用
前提:
this:没有继承也可以使用
super:只能在继承条件下使用
构造方法:
this:本类的构造
super:父类的构造!
方法重写
重写都是方法的重写,与属性无关
父类的引用指向了子类
重写只跟非静态方法有关,静态方法操作不了
重写:需要有继承关系,子类重写父类的方法
1. 方法名必须相同
2. 参数列表必须相同
3. 修饰符:范围可以扩大,但不能缩小。public > protected > default > private
4. 抛出的异常:范围,可以被缩小,但不能扩大
重写,子类的方法和父类必须一致,方法体不同
为什么要重写:
1. 父类的功能,子类不一定需要,或者不一定满足
Alt + Insert --> Override/Overload
2. 当子类需要父类的功能,但是功能还不完整,子类需要对父类的方法进行改进
多态
- 动态编译,可扩展性
- 同一个方法可以根据发送对象的不同而采用多种不同的行为方式
- 一个对象的实际类型是确定的,但可以指向对象的应用的类型有很多
- 多态存在的条件
- 有继承关系
- 子类重写父类方法
- 父类引用指向子类对象
- 注意:多态是方法的多态,属性没有多态性
一个对象的实际类型是确定的,可以指向的引用类型就不确定了;父类的引用指向子类
子类重写了父类的方法,执行子类的方法
对象执行哪些方法,主要看对象左边的类型,和右边关系不大!
子类能调用的方法都是自己的,或者是继承父类的
父类可以指向子类,但是不能调用子类独有的方法
instanceof和类型转换
System.out.println("X instanceof Y"); //能不能编译通过,要看X和Y是否存在父子关系
对象强制转换:将父对象强制转换成子对象,就可以使用子类型的方法了!
Person obj = new Student();
((Student) obj).go();
子类转换成父类,可能会丢失一些方法
static关键字:非静态方法可以调用静态方法
final修饰后不能被继承
抽象类
- abstract修饰符可以用来修饰方法,也可以修饰类;抽象方法&抽象类
- 抽象类中可以没有抽象方法,但抽象方法中的类一定要声明为抽象类
- 抽象类不能用 new 来创建对象,它是用来让子类继承的
- 抽象方法,只是方法的声明,没有方法的实现,它是让子类来实现的
- 子类继承抽象类,那么就必须要实现抽象类没有实现的抽象方法,否则子类也要声明为抽象类
java 的类是单继承,接口可以多继承
抽象类中可以写普通方法,抽象方法必须在抽象类中
接口
普通类:只有具体实现
抽象类:具体实现和规范(抽象方法)都有!
接口:只有规范!自己无法写方法;约束和实现分离:面向接口编程
接口就是规范,定义的是一组规则
接口的本质是契约,制定好之后大家都遵守
对对象的抽象,实际就是合理的去抽象
接口都需要有实现类
- interface 关键字
- 可以实现接口 implements 接口
- 实现接口的类,就需要重写接口中的方法
利用接口实现多继承
内部类
静态内部类 & 局部内部类 & 成员内部类 & 匿名内部类
通过外部类来实例化内部类
一个java类中可以有多个class类,但是只有一个 public class
异常
- Exception ,发生在运行期间
- 遇到的情况不可能非常完美
- 文件找不到、网络连接失败、非法参数
检查性异常、运行时异常、错误error
Error
Error 不可预见,由java虚拟机生成并抛出,大多数错误与代码及操作无关。
Virtual MachineError发生时,或者OutOfMemoryError发生时,JVM一般选择线程终止
JVM试图执行应用时,若类定义错误(NoClassDefFoundError),链接错误(LinkageError)。这些错误不可查,它们在应用程序的控制和处理能力之外,而且绝大多数程序运行时不允许出现的状况。
Exception
RuntimeException(运行时异常):这些异常是不检查异常,程序中可以选择捕获处理,也可以不处理
- ArrayIndexOutOfBoundsException(数组下标越界)
- NullPointerException(空指针异常)
- ArithmeticException(算术异常)
- MissingResourException(丢失资源)
- ClassNotFoundException(找不到类)
这些异常一般都是由程序错误引起的,程序应该从逻辑角度尽可能避免这类异常发生
Error 通常是灾难性的致命错误,是程序无法控制和处理的,JVM一般会选择终止线程;EXception通常情况下是可以被程序处理的,在程序中应该尽可能去处理这些异常
异常处理机制
捕获异常 & 抛出异常
try、catch、finally、throw、throws
try { //try监控区域
System.out.println(a/b);
} catch (ArithmeticException e) { //catch异常捕获
System.out.println("除数不能为0");
}finally { //处理善后工作,可以不存在
System.out.println("程序结束");
要捕获多个异常,要从小到大;若先捕获范围大的,则小范围异常被覆盖,不会执行
Ctrl + Alt + T 快捷键自动包裹选中的代码,可以快速捕获异常
throw 主动抛出异常,一般用在方法中
//在方法中处理不了这个异常,则方法上抛出异常
public void test(int a, int b) throws Exception{
if(b == 0){
throw new Exception("除数不能为0"); //主动地抛出异常,一般在方法中
}
}
自定义异常
java内置异常类足够用了,除此之外,用户还可以自定义异常。只需呀继承 Exception类即可
- 创建自定义异常类
- 在方法中通过throw关键字抛出异常对象
- 处理异常时,可以使用太容易 try—catch 语句捕获并处理;或者在方法的声明处通过 throws 指明抛出异常
- 在出现异常方法的调用者中捕获并处理异常
总结
- 处理运行时异常,采用逻辑去合理规避同时辅助try—catch处理
- 在多重catch块后面,可以加一个catch(Exception)来处理可能被遗漏的异常
- 对于不确定的代码,可以加上try—catch处理潜在异常
- 尽量去处理异常,而不是简单的printStackTrace()打印异常
- 具体如何处理异常,要根据不同的业务需求和异常类型去决定
- 尽量添加finally语句块去释放占用的资源

浙公网安备 33010602011771号