Java笔记(知识点及常见问题)
目录
- 1.%取余运算
- 2.光标连续跳过两行处理方法
- 3.常用的DOS命令
- 4.配置环境变量
- 5.注释
- 6.类
- 7.命名规范
- 8.数据类型
- 9.char类型
- 10.基本数据类型之间的运算规则
- 11.String 和任何类型做加法 都是起连接的作用。
- 12.原码、反码、补码
- 13.运算
- 14.a += 2 和 a = a+2 的区别
- 15.如果希望变量实现+2的操作,有几种方法?(前提:int = 10)
- 16.逻辑运算符
- 17.交换两个变量的值
- 18.三元运算符
- 19.if-else 的三种结构
- 20.如何获取一个随机数:10 – 99
- 21.判断两个东西是否相等 .equals( )
- 22.swith-case 中的表达式,只能是如下6种数据类型之一;
- 23.while循环
- 24.do-while循环至少会执行一次循环体
- 25.死循环
- 26.嵌套循环
- 27.break和continue关键字的使用
- 28.数组 Array
- 29.Arrays工具类的使用
- 30.数组中的常见异常:
- 31.冒泡排序 见MaoPaoArrayTest.java
- 32.数组的线性查找
- 33.数组的二分法查找
- 34.Java面向对象学习的三条主线:
- 35.类中属性的使用
- 36.方法的返回值
- 37.return关键字的使用
- 38.方法的使用中,可以调用当前类的属性或方法
- 39.匿名对象的使用
- 40.方法的重载
- 41.可变个数形参的方法
- 42.方法的形参的传递机制:值传递
- 43.若打印的值为char类型数组的变量名,则输出结果为遍历该数组。
- 44.判断两个字符串是否相等不能用 == 只能用 .equals
- 45.构造器的使用
- 46.继承性的格式: class A extends B{ }
- 47.继承的一些知识点
- 48.JavaBean是一种Java语言写成的可重用组件
- 49.如何调试程序
- 50.方法的重写
- 51.面向对象特征之三:多态性
- 52.面试题:==和equals( )的区别
- 53.Object类中toString()方法的使用:
- 54. Java中的JUnit单元测试
- 55.包装类的使用
- 56.数组也可以作为Object类的子类出现,可以调用Object类中声明的方法。
- 57.static关键字的使用。
- 58.单例设计模式
- 59.main()方法的使用说明:
- 60.类的成员之四:代码块(或初始化块)
- 61.对属性可以赋值的位置:
- 62.final修饰类和方法
- 63.abstract关键字的使用
- 64.System.currentTimeMillis()
- 65.质数又称素数,一个大于1的自然数,除了1和它自身外,不能被其他自然数整除的数叫质数。
- 66.在Java中类可以实现多个接口
- 67.接口的使用
- 68.构造器补充知识点
- 69.内部类
- 70.异常的概述
1.%取余运算
结果的符号取决于被模数的符号
int a=3 a=4
int b=a++ //先a的取值 后a自增 b=3
a=3 a=4
b=++a //先a自增 后取a的值 b=4
2.光标连续跳过两行处理方法
nextLine() 方法不能放在 nextInt( 代码段的后面,其实,他不是跳过你了,而是他已经有内容了,内容就是 \n。因为 nextInt() 接收一个整型字符,不会读取 \n,nextline() 读入一行文本,会读入 \n 字符。
【解决办法】:可以在 nextInt() 和 nextLine() 中间加一个 nextLine() 语句来接收这个 \n 。
3.常用的DOS命令
-
dir:列出当前目录下的文件以及文件夹。
-
md :创建目录。
-
rd :删除目录。
-
cd :进入指定目录。 (例: cd d:\java )
-
cd… :返回上一级目录。
-
cd\ :返回到根目录。
-
del :删除文件。
-
exit :退出dos命令行。
-
注意:要想执行某个磁盘的目录命令要先进入该磁盘(例: d: )
-
常用快捷键:
-
⬅ ➡ : 移动光标
-
⬆ ⬇ : 调阅历史操作命令
-
delete和backspace :删除字符
4.配置环境变量
配置环境变量的主要目的是:让jdk路径下的命令可以在任何路径下执行。
在path加javac所在路径
用JAVA_HOME= javac所在路径 去掉\bin
用%JAVA_HOME%\bin
**步骤一:**右键此电脑,点击属性。 **步骤二:**找到高级系统设置点击一下,点击环境变量。
**步骤三:**任选一个环境变量(用户或者系统)在path里面进行配置 注:最好配置在系统变量。
(path的功能:windows系统执行命令时要搜索的路径)。
验证是否成功 java javac
如果编译运行后中文乱码了将记事本的编码改成ANCI****
5.注释
1)单行注释 // 2) 多行注释 / / 不能嵌套使用
3)文档注释(Java特有)
/**
@author 指定Java程序的作者
@version 指定源文件的版本
*/
操作方式: javadoc -d mydoc -author -version HelloWorld.java
6.类
在一个Java源文件中可以声明多个class,但是最多只能有一个类声明为public型的。
加到跟编译的文件名一样的类上。
7.命名规范
命名大小写
-
1) 项目名全部小写
-
2)包名全部小写,如:import java.io.*
-
3)属性名用小写:如 String personName=“冰刃雪飘”;
-
4)变量名的首单词的首字母使用小写,如果变量的名字由多个单词组成,从第2个单词开始的其他单词的首字母使用大写。
例如:int max=0;//变量名
public int helloWord(){};//方法名 -
5) 类名首字母大写,如果类名由多个单词组成,每个单词的首字母都要大写。
如:public class MyFirstClass{} -
6)构造函数的名字要与类名称一样,所以也是大写开头。
-
7) 常量名全部大写,单词之间以下划线“_”隔开。
如:public static final String GAME_COLOR=”RED”; -
8)所有命名规则必须遵循以下规则:
名称只能由字母、数字、下划线、$符号组成
不能以数字开头
名称不能使用JAVA中的关键字。坚决不允许出现中文及拼音命名。
-
9)所有关键字中字母都是小写。
8.数据类型
基本数据类型:
1)数值型:
整型类型(byte 1字节,short 2字节,int 4字节,long 8字节) 1字节=8bit
浮点类型 (float 4字节,double 8字节)
2)字符型(char 2字节) C语言是1字节
3)布尔型(boolean)
引用数据类型:
类(class) String字符串属于类
接口(interface)
数组([])
定义一个char类型要用单引号 ’ ’ 例:char a=‘f’
class BooleanTest{
public static void main(String[] args){
boolean a = true;
if(a){
System.out.println("你是帅哥?是的");
}else{
System.out.println("你是美女");
}
}
}
9.char类型
表示方式:
1)声明一个字符:
char c1 = ‘a’;
2)转义字符:
char c2 = ‘\n’; 换行符
char c3 = ‘\t’; 制表符
3)直接用Unicode值来表示字符型常量
char c4 = ‘\u0123’; ‘\uxxxx’ 其中xxxx代表一个十六进制整数
如:’\u000a’表示\n
10.基本数据类型之间的运算规则
当容量小的数据类型的变量与容量大的数据类型的变量做运算时,结果自动提升为容量大的数据类型。
byte ,char ,short ——>int——>long——>float——>double
特别的:当byte ,char ,short ,三种类型的变量做运算时,结果为int。
强制类型转换:自动类型提升的逆运算。
1)需要使用强转符:()
2)注意点:强制类型转换,可能导致精度损失。
例: double a = 12.9;
精度损失1
int b = (int) a;
没有精度损失
long c = 123;
short d = (short) c;
精度损失2
int e = 128;
byte f = (byte) e;
11.String 和任何类型做加法 都是起连接的作用。
12.原码、反码、补码
正数的原码 反码 补码都一样。
负数的反码除符号位外,其他各位上的数都要取反。
负数的补码等于在反码的基础上+1。
计算机底层都以补码的方式来存储数据。
13.运算
%:取余运算
结果的符号与被模数的符号相同。
例: int a = -12; int a = 12;
int b = 5; int b = 5;
a%b = -2; a%b = 2;
14.a += 2 和 a = a+2 的区别
令a等于10
short a = 10;
a += 2;(不会改变数据本身类型)
int a = a + 2;(要改变数据本身类型)
15.如果希望变量实现+2的操作,有几种方法?(前提:int = 10)
方法一:num = num + 2;
方法二:num += 2;(推荐); 不会改变数据类型
16.逻辑运算符
区分& 与 && (且的意思)
相同点1:& 与 && 的运算结果相同
相同点2:当符号左边时true时,二者都会执行符号右边的运算
不同点:当符号左边是false时,&继续执行符号右边的运算,&&不再执行符号右边的运算
开发中,推荐使用&&
区分| 与 || (或的意思)
相同点1:| 与 || 的运算结果相同
相同点2:当符号左边时flase时,二者都会执行符号右边的运算
不同点:当符号左边是true时,|继续执行符号右边的运算,||不再执行符号右边的运算
开发中,推荐使用||
17.交换两个变量的值
int num1 = 10;
int num2 = 20;
System.out.println("num1 = " + num1 + ", num2 = " + num2);
方式一:定义临时变量的方式
int temp = num1;
num1 = num2;
num2 = temp;
System.out.println("num1 = " + num1 + ", num2 = " + num2);
方式二:好处:不用定义临时变量省空间
弊端:1)相加操作可能超出存储范围。 2)有局限性:只能适用于数值类型
num1 = num1 + num2;
num2 = num1 - num2;
num1 = num1 - num2;
方式三:使用位运算符
有局限性:只能适用于数值类型
num1 = num1 ^ num2;
num2 = num1 ^ num2;
num1 = num1 ^ num2;
18.三元运算符
(条件表达式)?表达式1: 表达式2;
条件表达式为true,运算后结果是表达式1;
条件表达式为false,运算后结果是表达式2;
- 表达式1和表达式2为同一种类型
例:
int m = 12 ;
int n = 5;
int max = (m > n)? m : n;
System.out.println(max);
获取三个数的最大值
int n1 = 12;
int n2 = 30;
int n3 = -43;
int max1 = (n1 > n2)? n1 : n2;
int max2 = (max1 > n3)? max1 : n3;
System.out.println("三个数中的最大值为:" + max2);
凡是可以是用三元运算符都可以用 if-else,反之不成立
19.if-else 的三种结构
第一种:
if(条件表达式){
执行表达式
}
第二种:二选一
if(条件表达式){
执行表达式1
}else{
执行表达式2
}
第三种:多选一
if(条件表达式){
执行表达式1
}else if(条件表达式){
执行表达式2
}else if(条件表达式){
执行表达式3
}...
else{
执行表达式n
}
如果if-else只有一行执行语句时则可以省略大括号{}
20.如何获取一个随机数:10 – 99
调用Math类下的random方法
random方法表示返回值为正的double类型,且范围为[0.0 ,1.0)
double value = Math.random() * 90 + 10; 范围为[10.0 ,100.0)
结果类型仍然为double类型需要强转为int类型
int value = (int) (Math.random() * 90 + 10); 范围为[10 ,99]
公式:[a,b] :(int)(Math.random() * (b-a+1) + a)
21.判断两个东西是否相等 .equals( )
22.swith-case 中的表达式,只能是如下6种数据类型之一;
byte , short , char , int , 枚举类型 (JDK5.0新增) ,String类型(JDK7.0新增)
格式
swith(表达式){
case 常量1:
执行语句1;
break;
case 常量2:
执行语句2;
break;
case 常量3:
执行语句3;
break;
default:
执行语句n;
break;
}
23.while循环
说明:
1)写while循环千万要小心不要丢了迭代条件,一旦丢了,就可能导致死循环。
2)我们写程序,要避免出现死循环。
3)for循环和while循环是可以相互转换的!
区别:for循环和while循环的初始条件部分的作用范围不同。
例:int i = 1;
while(i <= 100){
if(i % 2 == 0){
System.out.println(i);
}
i++;
}
24.do-while循环至少会执行一次循环体
例:int num = 1;
do{
if(num % 2 == 0){
System.out.println(num);
}
num++;
}while(num <= 100);
开发中,使用for和while更多一些。较少使用do-while
25.死循环
1)for( ; ; ) 2) while(true)
结束循环的两种方式:
一、循环条件部分返回false。
二、在循环体中,执行break。
26.嵌套循环
说明:
1)内层循环结构遍历一遍,只相当于外层循环循环体执行了一次
2)假设外层循环需要执行m次,内层循环需要执行n次。此时内层循环的循环体一共执行了m*n次
for(int i = 1;i <= 5;i++){
//控制行数
for(int j = 1;j <= i;j++){
//控制列数
System.out.print("*");
}
System.out.println();
}
27.break和continue关键字的使用
使用范围 | 循环中使用的作用(不同点) | 相同点 | |
---|---|---|---|
break: | swith-case循环结构中 | 结束当前循环 | 关键字后面不能声明执行语句 |
continue: | 循环结构中 | 结束当次循环 | 关键字后面不能声明执行语句 |
结束指定标识的一层循环结构:
label:for( ){
label:for( ){
break label; continue label;
} }
28.数组 Array
数组的概述:数组(Array),是多个相同类型数据按一定顺序排列
的集合,并使用一个名字命名,并通过编号的方式
对这些数据进行统一管理。
数组的常见概念:
1)数组名
2)下标(或索引) 从0开始
3)元素
4)数组的长度:元素的个数
数组的特点:
数组是有序排列的
数组属于引用数据类型的变量,数组的元素既可以是基本数据类型也可以是引用数据类型。
创建数组对象会在内存中开辟一整块连续的空间
数组的长度一但确定,无法修改
数组的分类:
按照维数:一维数组,二维数组…
按照数组元素的类型:基本数据类型的数组,引用数据类型的数组
一维数组的使用:
1)一维数组的声明和初始化
2)如何调用数组的指定位置的元素
3)如何获取数组的长度
4)如何遍历数组元素
5)数组元素的默认初始化值
数组元素是整形:0
数组元素是浮点型:0.0
数组元素是char类型: 0或’\u0000’,而非’0’
数组元素是boolean型:false 相当于二进制数的0
数组元素引用数据类型时:null
6)数组的内存解析
二维数组的初始化
外层元素的初始化值为:地址值
内层元素的初始化值为:与一维数组初始化情况相同
29.Arrays工具类的使用
1.Arrays.equals(int[] a,int[] b) 判断两个数组是否相等
例:int[] arr1 = new int[]{
1,2,3,4};
int[] arr2 = new int[]{
1,3,2,4};
boolean isEquals = Arrays.equals(arr1,arr2);
System.out.println(isEquals);
2.Arrays.toString(arr1) 输出数组信息
System.out.println(Arrays.toString(arr1));
3.Arrays.fill(arr1,10) 把数组里的元素都变为10
4.Arrays.sort(arr2) 将数组里的元素按照从小到大的顺序进行排序
5.Arrays.binarySearch(arr3,210) 找目标元素在数组中的索引值
int[] arr3 = new int[]{
-98,-34,2,34,54,66,79,105,210,333};
int index = Arrays.binarySearch(arr3,210);
System.out.println(index); 返回值为负数则未找到
30.数组中的常见异常:
1.数组角标越界的异常:ArrayIndexOutOfBoundsExcetion
2.空指针异常:NullPointerException
31.冒泡排序 见MaoPaoArrayTest.java
int[] arr = new int[]{
43,32,76,-98,0,64,33,-21,32,99};
for(int i = 0;i < arr.length - 1;i++){
for(int j = 0;j < arr.length - 1 - i;j++){
if(arr[j] > arr[j+1]){
int temp = arr[j];
arr[j] = arr[j+1];
arr[j + 1] = temp;
}
}
}
32.数组的线性查找
String[] arr = new String[]{
"JJ","DD","MM","BB","GG","AA"};
String dest = "BB";
boolean isFlag = true;
for(int i = 0;i < arr.length;i++){
if(dest.equals(arr[i])){
System.out.println("找到了指定的元素;位置为:" + i);
isFlag = false;
break;
}
}
if(isFlag){
System.out.println("很遗憾,没有找到!");
}
33.数组的二分法查找
int[] arr2 = new int[]{
-98,-34,2,34,54,66,79,105,210,333};
int dest1 = -34;
int head = 0;
int end = arr2.length - 1;
boolean isFlag1 = true;
while(head <= end){
int middle = (head + end)/2;
if(dest1 == arr2[middle]){
System.out.println("找到了指定的元素,位置为:" + middle);
isFlag1 = false;
break;
}else if(arr2[middle] > dest1){
end = middle - 1;
}else{
head = middle + 1;
}
}
if(isFlag1){
System.out.println("很遗憾没有找到");
}
34.Java面向对象学习的三条主线:
1.Java类及类的成员:
属性,方法,构造器;代码块,内部类
2.面向对象的三大特征:
封装性,继承性,多态性,(抽象性)
3.其他关键字:
this,super,static,final,abstract,interface,package,import等
35.类中属性的使用
属性(成员变量)VS 局部变量
1.相同点:
1.1定义变量的格式:数据类型 变量名 = 变量值
1.2先声明,后使用
1.3变量都有其对应的作用域
2.不同点:
2.1在类中声明的位置的不同
属性:直接定义在类的一对{ }内
局部变量:声明在方法内,方法形参,代码块内,构造器形参,构造器内部的变量
2.2关于System.out.println(p2.isMale);权限修饰符的不同
属性:可以在声明属性时,指明其权限,使用权限修饰符
常用的权限修饰符:private,public,缺省,protected —–>封装性
目前:大家声明属性时,都使用缺省就可以了
局部变量:不可以使用权限修饰符
2.3默认初始化值的情况:
属性:类的属性,根据其类型,都有默认初始化值
整型(byte,short,int,long):0
浮点型(float,double):0.0
字符型(char):0 (或’\u0000’)
布尔型(boolean):false
引用数据类型(类,数组,接口):null
局部变量:没有默认初始化值
意味着:我们在调用局部变量之前,一定要显示赋值
特别地:形参在调用时,我们赋值即可
2.4在内存中加载的位置:
属性:加载到堆空间中(非static)
局部变量:加载到栈空间
36.方法的返回值
有返回值 VS 无返回值
1)如果方法有返回值,则必须在方法声明时,指定返回值的类型。
同时,在方法中,需要使用return关键字来返回指定类型的变量或常量:”return 数据“
2)如果方法没有返回值,则方法声明时,使用void来表示。通常,没有返回值的方法中,使用return。
但是,如果使用的话,只能”return;“表示结束此方法的意思。
37.return关键字的使用
1、使用范围:
使用在方法体中
2、作用:
1)结束方法
2)针对有返回值类型的方法,使用”return 数据”方法返回所要的数据。
3.注意点:
return关键字后面不可以声明执行语句。
38.方法的使用中,可以调用当前类的属性或方法
特殊的:方法A中又调用了方法A:递归方法。
39.匿名对象的使用
1、理解:我们创建的对象,没有赋给他一个变量名。即为匿名对象。
2、特征:匿名对象只能使用一次。
例:new Student( ).show( );
40.方法的重载
1、定义:在同一个类中,允许存在一个以上的同名方法,只要它们的参数个数或者参数类型不同即可。
“两同一不同”:同一个类、相同方法名
参数列表个数不同,参数类型不同
2、举例:
Arrays类中重载的sort( ) / binarySearch( )
3、判断是否重载:
跟方法的权限修饰符、返回值类型、形参变量名、方法体都没有关系!
4、在通过对象调用方法时,如何确定某一个指定的方法:
方法名 ——–> 参数列表
41.可变个数形参的方法
1、jdk 5.0新增的内容
2、具体使用:
2.1 可变个数形参的格式:数据类型 . . . 变量名
public void show(String … str){
}
2.2 当调用可变个数形参的方法时,传入的参数个数可以是:0个,1个,2个。。。
2.3 可变个数形参的方法与本类中方法名相同,形参不同的方法之间构成重载。
2.4 可变个数形参的方法与本类中方法名相同,形参类型也相同的数组之间不构成重载。
换句话说,二者不能共存。
2.5 可变个数形参在方法的形参中,必须声明在末尾。
public void show(String … str,int i){
}
2.6 可变个数形参在方法的形参中,最多只能声明一个可变形参。
42.方法的形参的传递机制:值传递
1、形参:方法定义时,声明的小括号内的参数
实参:方法调用时,实际传递给形参的数据
2、值传递机制:
如果参数是基本数据类型,此时实参赋给形参的是实参真实存储的数据值。
如果参数是引用数据类型,此时实参赋给形参的是实参存储数据的地址值。
43.若打印的值为char类型数组的变量名,则输出结果为遍历该数组。
例:char[] arr1 = new char[]{
'a','b','c'};
System.out.println(arr1); //abc
44.判断两个字符串是否相等不能用 == 只能用 .equals
字符串用==时比较的时两个字符串的地址值。
45.构造器的使用
一、构造器的作用:
1、创建对象:new + 构造器
Person p = new Person( ); 注:Person( )为构造器
2、初始化对象的属性
3、一个类中定义的多个构造器,彼此构成重载
4、一旦我们显示的定义了类的构造器之后,系统就不再提供默认的空参构造器
5、一个类中,至少会有一个构造器
二、说明:
1、如果没有显式的定义类的构造器的话,则系统默认提供一个空参的构造器
2、定义构造器的格式:权限修饰符 类名(形参列表){ }
例:public Person( ){
//默认的构造器
}
46.继承性的格式: class A extends B{ }
A:子类、派生类、subclass
B:父类、超类、基类、superclass
2.1体现:一旦子类A继承父类B以后,子类A中就获取了父类B中声明的所有的属性和方法
特别的,父类中生命为private的属性或方法,子类继承父类以后,仍然认为获取了父类中私有的结构。只是因为封装性的影响,使得子类不能直接调用父类的结构而已。
2.2子类继承父类以后,还可以声明自己特有的属性或方法:实现功能的拓展。
子类和父类的关系不同于子集和集合的关系。
47.继承的一些知识点
一、Java中关于继承性的规定:
1.一个类可以被多个子类继承。
2.Java中类的单继承性:一个类只能有一个父类
3.子父类时相对的概念。
4.子类直接继承的父类,称为:直接父类。间接继承的父类称为:间接父类
5.子类继承父类以后,就获取了直接父类以及所有间接父类中声明的属性和方法
二、
1.如果我们没有显式的声明一个类的父类的话,此类继承于java.lang.Object类
2.所有的Java类(除java.lang.Object类之外)都直接或间接的继承于java.lang.Object类
3.意味着,所有的Java类具有java.lang.Object类声明的功能
48.JavaBean是一种Java语言写成的可重用组件
所谓JavaBean,是指如下标准的Java类:
>类是公共的
>有一个无参的公共的构造器
>有属性,且有对应的get、set方法
49.如何调试程序
1.System.out.println()在程序中加一些输出语句
2.Eclipse – Debug调试
2.1设置断点双击左边蓝色竖线框对应的代码行、
50.方法的重写
1.重写:子类继承父类以后,可以对父类中同名同参数的方法,进行覆盖操作
2.应用:重写以后。当创建子类对象以后,通过子类对象调用父类中的同名同参数的方法时,实际执行的是子类重写父类的方法。
3.重写的规定:
方法的声明:权限修饰符 返回值类型 方法名(形参列表) throws 异常的类型{
方法体
}
约定俗称:子类中的叫重写的方法,父类中的叫被重写的方法
①子类重写的方法的方法名和形参列表与父类被重写的方法的方法名和形参列表相同
②子类重写的方法的权限修饰符不小于父类被重写的方法的权限修饰符
>特殊情况:子类不能重写父类中声明为private权限的方法
③返回值类型:
>父类被重写的方法的返回值类型是void,则子类重写的方法的返回值类型只能是void
>父类被重写的方法的返回值类型是A类型,则子类重写的方法的返回值类型可以是A类型或A类的子类(引用数据类型)
>父类被重写的方法的返回值类型是基本数据类型(比如:double),则子类重写的方法的返回值类型必须是相同的数据类型(double)
④子类重写的方法抛出的异常类型不大于父类被重写的方法抛出的异常类型
子类和父类中的同名参数的方法要么都声明为非static的(考虑重写),要么都声明为static的(不是重写)
51.面向对象特征之三:多态性
1、理解多态性:可以理解为一个事物的多种形态。
2、何为多态性:
对象的多态性:父类的引用指向子类的对象(或子类的对象赋给父类的引用)
3、多态的使用:虚拟方法调用
有了对象的多态性以后,我们在编译期,只能调用父类中声明的方法,但在运行期,我们实际执行的是子类重写父类的方法。
总结:编译,看左边;运行,看右边。
4、多态性的使用前提:①类的继承关系②方法的重写
5、对象的多态性:只适用于方法,不适用于属性。(编译和运行都看左边)
6、多态性的对象不能调用子类特有的方法、属性。
7、有了对象的多态性以后,内存中实际上是加载了子类特有的属性和方法的,但是由于变量声明为父类类型,导致编译时只能调用父类中声明的属性和方法。子类特有的属性和方法不能调用。
8、如何才能调用子类特有的属性和方法?
Person p2 = new Man( ); **向下转型:使用强制类型转换符** Man m1 = (Man)p2; m1.earnMoney( ); 使用强转时,可能出现ClassCastException的异常。 Woman w1 = (Woman)p2; **这是错的**
使用instanceof
使用情境:为了避免在向下转型时出现ClassCastException的异常,我们在向下转型之前,先进行instanceof的判断,一旦返回true,就进行向下转型。如果返回flase,不进行向下转型。
如果 a instanceof A返回true,则a instanceof B也返回true。
其中,类B是类A的父类。
a instanceof A:判断对象a是否是类A的实例。如果是,返回true;如果不是,返回false。
if(p2 instanceof Woman){
Woman w1 = (Woman)p2;
w1.goshopping( );
System.out.println(“Woman”);
}
if(p2 instanceof Man){
Man m2 = (Man)p2;
m2.goshopping( );
System.out.println(“Man”);
}
52.面试题:==和equals( )的区别
一、回顾==的使用
==:运算符
1、可以使用在基本数据类型变量和引用数据类型变量中
2、如果比较的是基本数据类型变量:比较两个变量保存的数据是否相等。(不一定类型要相同)
如果比较的是引用数据类型变量:标间两个对象的地址值是否相同,及两个引用是否指向同一个对象实体。
补充:==符号使用时,必须保证符号左右两边的变量类型一致。
二、equals( )方法的使用:
1、是一个方法,而非运算符
2、只能适用于引用数据类型
3、Object类中equals( )的定义:
public boolean equals(Object obj){
return(this == obj);
}
说明:Object类中定义的equals( )和==的作用是相同的:比较两个对象的地址值是否相同,及两个引用是否指向同一个对象实体。
4、像String、Date、File、包装类等都重写了Object类中的equals( )方法。重写以后,比较的不是两个引用的地址是否相同,而是比较两个对象的“实体内容”是否相同。
5、通常情况下,我们自定义的类如果使用equals( )的话,也通常是比较两个对象的“实体内容”是否相同。那么,我们就需要对Object类中的equals( )进行重写。
重写的规则:比较两个对象的实体内容是否相同。
53.Object类中toString()方法的使用:
1.当我们输出一个对象的引用时,实际上就是调用当前对象的toString()
2.Object类中toString()的定义:
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
3.像String、Date、File、包装类等都重写了Object类中的toString()方法。
使得在调用对象的toString()时,返回”实体内容”信息
4.自定义类也可以重写toString()方法,当调用此方法时,返回对象的”实体内容”
54. Java中的JUnit单元测试
步骤:
1.选中当前工程 – 右键选择:build path – add libraries – JUnit – 下一步
2.创建一个Java类进行单元测试。
此时的Java类要求:①此类是公共的②此类提供公共的无参的构造器
3.此类中声明单元测试方法。
此时的单元测试方法:方法的权限是public,没有返回值,没有形参
4.此单元测试方法上需要声明注解:@Test,并在单元测试类中导入:
5.声明好单元测试方法以后,就可以在方法体内测试相关的代码。
6.写完代码以后,左键双击单元测试方法名,右键:run as – JUnit Test
如果:
1.如果执行结果没有任何异常:绿条
2.如果执行结果出现异常:红条
55.包装类的使用
见Java项目 javasetest—>test4—>WrapperTest
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nnbddy7N-1650024581460)(…/AppData/Roaming/Typora/typora-user-images/image-20220218151017998.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-48PbVREY-1650024581463)(…/AppData/Roaming/Typora/typora-user-images/image-20220218200641991.png)]
56.数组也可以作为Object类的子类出现,可以调用Object类中声明的方法。
57.static关键字的使用。
1.static:静态的
2.static:可以用来修饰:属性、方法、代码块、内部类
3.使用static修饰属性:静态变量(或类变量)
3.1属性,是否使用static修饰,又分为:静态属性 vs 非静态属性(实例变量)
实例变量:当我们创建了类的多个对象,每个对象都独立的拥有一套类中的非静态属性。
当修改其中一个对象中的非静态属性时,不会导致其他对象中同样的属性值的修改。
静态变量:当我们创建了类的多个对象,多个对象共享同一个静态变量。当通过某一个对象修改静态变量时,会导致
其他对象调用此静态变量时,是修改过了的。
3.2 static修饰属性的其他说明:
① 静态变量随着类的加载而加载。可以通过”类 . 静态变量”的方式进行调用
② 静态变量的加载要早于对象的创建。
③ 由于类只加载一次,则静态变量在内存中也只会存在一份:存在方法区的静态域中。
④类和对象分别可以调用:
类对象 | 实例对象 | |
---|---|---|
类 | yes | no |
对象 | yes | yes |
3.3 静态属性举例:System.out;Math.PI;
4.使用static修饰方法:静态方法
① 随着类的加载而加载,可以通过”类.静态方法”的方式进行调用。
②
类对象 | 实例对象 | |
---|---|---|
类 | yes | no |
对象 | yes | yes |
③ 静态方法中,只能调用静态的方法或属性
非静态方法中,既可以调用非静态的方法或属性,也可以调用静态的方法或属性
5.static注意点:
5.1 在静态的方法内,不能使用this关键字、super关键字
5.2 关于静态属性和静态方法的使用,大家都从生命周期的角度去理解。
6.(属性)开发中,如何确定一个属性是否声明为static的?
属性是可以被多个对象所共享的,不会随着对象的不同而不同的。
-
类中的常量也常常声明为static
(方法)开发中,如何确定一个方法是否要声明为static的?
-
>操作静态属性的方法,通常设置为static的。
-
>工具类中的方法,习惯上声明为static的。比如:Math、Arrays、Collections
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PaM3U5OU-1650024581464)(…/AppData/Roaming/Typora/typora-user-images/image-20220221203209119.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kfTuo7aW-1650024581465)(…/AppData/Roaming/Typora/typora-user-images/image-20220221203235767.png)]
静态的属性一般不会加到构造器里。
58.单例设计模式
1.所谓类的单例设计模式,就是采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例。
2.如何实现?
饿汉式 vs懒汉式
单例模式的饿汉式实现
public class SingletonTest1 {
public static void main(String[] args) {
Bank bank1 = Bank.getInstance();
Bank bank2 = Bank.getInstance();
System.out.println(bank1 == bank2);
}
}
//饿汉式
class Bank{
//1.私有化类的构造器
private Bank() {
}
//2.内部创建类的对象
//要求此对象也必须声明为静态的
private static Bank instance = new Bank();
//3.提供公共的静态的方法,返回类的对象
public static Bank getInstance() {
return instance;
}
}
单例模式的懒汉式实现
* public class SingletonTest2 {
public static void main(String[] args) {
Order order1 = Order.getInstance();
Order order2 = Order.getInstance();
System.out.println(order1 == order2);
}
}
class Order{
//1.私有化类的构造器
private Order() {
}
//2.声明当前类对象,没有初始化
//4.此对象也必须声明为static的
private static Order instance = null;
//3.声明public、static的返回当前类对象的方法
public static Order getInstance() {
if(instance == null) {
instance = new Order();
}
return instance;
}
}
3.区分饿汉式和懒汉式
坏处 | 好处 | |
---|---|---|
饿汉式 | 对象加载时间过长 | 饿汉式是线程安全的 |
懒汉式 | 延迟对象的创建 | 目前的写法坏处:线程不安全。—>到多线程内容时。再修改 |
59.main()方法的使用说明:
1.main()方法作为程序的入口
2.main()方法也是一个普通的静态方法
3.main()方法可以作为我们与控制台交互的方式。(之前,使用Scanner)
60.类的成员之四:代码块(或初始化块)
1.代码块的作用:用来初始化类、对象(初始化块)
2.代码块如果有修饰的话,只能使用static
3.分类:静态代码块 vs 非静态代码块
4.静态代码块
-
内部可以有输出语句
-
随着类的加载而执行,而且只执行一次
-
作用:初始化类的信息
-
如果一个类中定义了多个静态代码块,则按照声明的先后顺序执行
-
静态代码块的执行要优先于非静态代码块的执行。
-
静态代码块内只能调用静态的属性、静态的方法,不能调用非静态的结构
5.非静态代码块
-
内部可以有输出语句
-
随着对象的创建而执行
-
每创建一个对象,就执行一次非静态代码块
-
作用:可以在创建对象时,对对象的属性等进行初始化
-
如果一个类中定义了多个非静态代码块,则按照声明的先后顺序执行
-
非静态代码块内可以调用静态的属性,静态的方法,或非静态的属性、非静态的方法
* public class BlockTest { public static void main(String[] args) { String desc = Person.desc; System.out.println(desc); Person p1 = new Person(); Person p2 = new Person(); System.out.println(p1.age); Person.info(); ``` } } class Person{ //属性 String name; int age; static String desc = "我是一个人"; //构造器 public Person() { } public Person(String name,int age) { this.name = name; this.age = age; } //static的 代码块 static{ System.out.println("hello,static block-2"); } static{ System.out.println("hello,static block-1"); desc = "我是一个爱学习的人"; } //非static的代码块 { System.out.println("hello,block-1"); age = 1; } { System.out.println("hello,block-2"); } //方法 public void eat() { System.out.println("吃饭"); } @Override public String toString() { return "Person [name=" + name + ", age=" + age + "]"; } public static void info() { System.out.println("我是一个快乐的人!"); } }
61.对属性可以赋值的位置:
①默认初始化
②显式初始化⑤在代码块中赋值
③构造器中初始化
④有了对象以后,可以通过”对象.属性”或”对象.方法”的方式,进行赋值
执行的先后顺序:① – ② / ⑤ – ③ – ④
62.final修饰类和方法
final:最终的
1.final可以用来修饰的结构:类、方法、变量
2.final 用来修饰一个类:此类不能被其他类所继承
比如:String类、System类、StringBuffer类
3.final 用来修饰方法:表明此方法不可以被重写
比如:Object类中getClass();
4.final 用来修饰变量:此时的”变量”就称为是一个常量
-
4.1 final修饰属性:可以考虑赋值的位置有:显式初始化、代码块中初始化、构造器中初始化、
-
4.2 final修饰局部变量:
-
尤其是使用final修饰形参时,表明此形参是一个常量。当我们调用此方法时,给常量形参赋一个实参。
-
一旦赋值以后,就只能在方法体内使用此形参,但不能进行重新赋值。
- static final 用来修饰属性:叫全局常量
63.abstract关键字的使用
1.abstract:抽象的
2.abstract可以用来修饰的结构:类、方法
3.abstract修饰类:抽象类
此类不能实例化
抽象类中一定有构造器,便于子类对象实例化时调用(涉及:子类对象实例化的全过程)
开发中,都会提供抽象类的子类,让子类对象实例化,完成相关的操作
4.abstract修饰方法:抽象方法
抽象方法只有方法的声明,没有方法体
包含抽象方法的类,一定是一个抽象类。反之,抽象类中可以没有抽象方法。
若子类重写了父类中的所有的抽象方法后,此子类方可实例化
若子类没有重写父类中的所有的抽象方法,此子类也是个抽象类,需要使用abstract修饰
5.abstract使用上的注意点:
-
1.abstract不能用来修饰:属性、构造器等结构
-
2.abstract不能用来修饰私有方法、静态方法、final的方法
64.System.currentTimeMillis()
获取当前时间距离1970-01-01 00:00:00 的毫秒数
65.质数又称素数,一个大于1的自然数,除了1和它自身外,不能被其他自然数整除的数叫质数。
66.在Java中类可以实现多个接口
67.接口的使用
1.接口使用interface关键字来定义
2.Java中接口和类是并列的两个结构
3.如何定义接口:定义接口中的成员
3.1 JDK7及以前:只能定义全局常量和抽象方法
全局常量:声明为public static final的。但是书写时,可以省略不写
抽象方法:声明为public abstract的
3.2 JDK8:除了定义全局常量和抽象方法之外,还可以定义静态方法、默认方法
4.接口中不能定义构造器的!意味着接口不能实例化
5.Java开发中,接口都通过让类去实现(implements)的方式来使用
- 如果实现类覆盖了接口中的所有抽象方法,则此实现类就可以实例化
- 如果实现类没有覆盖接口中所有的抽象方法,则此实现类仍为一个抽象类
6.Java类可以实现多个接口 – – – >弥补了Java单继承性的局限性
格式:class AA extends BB implements CC,DD,EE
7.接口与接口之间可以继承,而且可以多继承
8.接口的具体使用,体现多态性
9.接口,实际上可以看作是一种规范
面试题:抽象类与接口有哪些异同?
public class InterfaceTest {
public static void main(String[] args) {
System.out.println(Flyable.MAX_SPEED);
System.out.println(Flyable.MIN_SPEED);
Plane plane = new Plane();
plane.fly();
}
}
interface Flyable{
//全局常量
public static final int MAX_SPEED = 7900;//第一宇宙速度
int MIN_SPEED = 1;//省略了public static final
//抽象方法
public abstract void fly();
void stop();//省略了public abstract
}
interface Attackable{
void attack();//省略了public abstract
}
class Plane implements Flyable{
@Override
public void fly() {
System.out.println("通过引擎起飞");
}
@Override
public void stop() {
System.out.println("驾驶员减速停止");
}
}
class Kite implements Flyable{
@Override
public void fly() {
// TODO Auto-generated method stub
}
@Override
public void stop() {
// TODO Auto-generated method stub
}
}
class Bullet extends Object implements Flyable,Attackable,CC{
@Override
public void attack() {
// TODO Auto-generated method stub
}
@Override
public void fly() {
// TODO Auto-generated method stub
}
@Override
public void stop() {
// TODO Auto-generated method stub
}
@Override
public void method1() {
// TODO Auto-generated method stub
}
@Override
public void method2() {
// TODO Auto-generated method stub
}
}
//***********************************
interface AA{
void method1();
}
interface BB{
void method2();
}
interface CC extends AA,BB{
}
接口的使用
- 1.接口使用上也满足多态性
- 2.接口,实际上就是定义了一种规范
- 3.开发中,体会面向接口编程!
public class USBTest {
public static void main(String[] args) {
Computer com = new Computer();
//1.创建了接口的非匿名实现类的非匿名对象
Flash flash = new Flash();
com.transferDate(flash);
//2.创建了接口的非匿名实现类的匿名对象
com.transferDate(new Printer());
//3.创建了接口的匿名实现类的非匿名对象
USB phone = new USB() {
@Override
public void start() {
System.out.println("手机开启工作");
}
@Override
public void stop() {
System.out.println("手机结束工作");
}
};
com.transferDate(phone);
//4.创建了接口的匿名实现类的匿名对象
com.transferDate(new USB() {
@Override
public void start() {
System.out.println("mp3开启工作");
}
@Override
public void stop() {
System.out.println("mp3结束工作");
}
});
}
}
class Computer{
public void transferDate(USB usb) {//USB usb = new Flash();
usb.start();
System.out.println("具体传输数据的细节");
usb.stop();
}
}
interface USB{
//常量: 定义了长、宽、最大最小的传输速度等
void start();
void stop();
}
class Flash implements USB{
@Override
public void start() {
System.out.println("U盘开启工作");
}
@Override
public void stop() {
System.out.println("U盘结束工作");
}
}
class Printer implements USB{
@Override
public void start() {
System.out.println("打印机开启工作");
}
@Override
public void stop() {
System.out.println("打印机结束工作");
}
}
JDK8:除了定义全局常量和抽象方法之外,还可以定义静态方法、默认方法
public class SubClassTest {
public static void main(String[] args) {
SubClass s = new SubClass();
// s.method1();
// SubClass.method1();
//知识点1:接口中定义的静态方法,只能通过接口来调用。
CompareA.method1();
//知识点2:通过实现类的对象,可以调用接口中的默认方法
//如果实现类重写了接口中的默认方法,调用时,仍然调用的是重写以后的方法
s.method2();
//知识点3:如果子类(或实现类)继承的父类和实现的接口中声明了同名同参数的方法,
//那么子类在没有重写此方法的情况下,默认调用的是父类中的同名同参数的方法。- - ->类优先原则
//知识点4:如果实现类实现了多个接口,而这多个接口中定义了同名同参数的默认方法,
//那么在实现类没有被重写此方法的情况下,报错。 - - ->接口冲突
//这就需要我们必须在实现类中重写此方法
s.method3();
}
}
class SubClass extends SuperClass implements CompareA,CompareB{
//重写接口默认方法
public void method2() {
System.out.println("SubClass:上海");
}
public void method3() {
System.out.println("SubClass:深圳");
}
//知识点5:如何在子类(或实现类)的方法中调用父类、接口中被重写的方法
public void myMethod() {
method3();//调用自己定义的重写的方法
super.method3();//调用的是父类中声明的
//调用接口中的默认方法
CompareA.super.method3();
CompareB.super.method3();
}
}
68.构造器补充知识点
1.若父类没有带参的构造器,则子类不用写父类的构造器。
2.若父类只有带参的构造器,则子类必须写构造器。
3.若父类既有空参的构造器又有带参的构造器,则子类可写可不写构造器
69.内部类
类的成员之五:内部类
1.Java中允许将一个类A声明在另一个类B中,则类A就是内部类,类B称为外部类
2.内部类的分类:
成员内部类(静态、非静态) vs 局部内部类(方法内、代码块内、构造器内)
3.成员内部类:
一方面,作为外部类的成员:
调用外部类的结构
可以被static修饰
可以被四种不同的权限修饰
另一方面,作为一个类:
类内可以定义属性、方法、构造器等
可以被final修饰,表示此类不能被继承。言外之意,不使用final,就可以被继承
可以被abstract修饰,表示不能被实例化
4.关注如下的3个问题
4.1如何实例化成员内部类的对象
4.2如何在成员内部类中区分调用外部类的结构
4.3开发中局部内部类的使用
public class InnerClassTest {
public static void main(String[] args) {
//创建Dog实例(静态的成员内部类):
Person.Dog dog = new Person.Dog();
dog.show();
//创建Bird实例(非静态的成员内部类):
// Person.Bird bird = new Person.Bird();//错误的
Person p = new Person();
Person.Bird bird = p.new Bird();
bird.sing();
System.out.println("*****************");
bird.display("黄鹂");
}
}
class Person{
String name = "小明";
int age;
public void eat() {
System.out.println("人:吃饭");
}
//静态成员内部类
static class Dog{
String name;
int age;
public void show() {
System.out.println("卡拉是条狗");
}
}
//非静态成员内部类
class Bird{
String name = "杜鹃";
public Bird(){
}
public void sing() {
System.out.println("我是一只小小鸟");
Person.this.eat();//调用外部非静态的属性
eat();
//没有重名的话可以之间调
}
public void display(String name) {
//都有name的时候怎么调
System.out.println(name);//方法的形参name
System.out.println(this.name);//内部类Bird类的name
System.out.println(Person.this.name);//外部类Person类的name
}
}
public void method() {
//局部内部类
class AA{
}
}
{
//局部内部类
class BB{
}
}
public Person(){
//局部内部类
class CC{
}
}
}
局部内部类
public class InnerClassTest1 {
//开发中很少见
public void method() {
//局部内部类
class AA{
}
}
//返回一个实现了Comparable接口的类的对象
public Comparable getComparable() {
//创建了一个实现了Comparable接口的类:局部内部类
//方式一:
// class MyComparable implements Comparable{
//
// @Override
// public int compareTo(Object o) {
// // TODO Auto-generated method stub
// return 0;
// }
//
// }
//
// return new MyComparable();
//方式二:
return new Comparable() {
@Override
public int compareTo(Object o) {
// TODO Auto-generated method stub
return 0;
}
};
}
}
70.异常的概述
一、异常的体系结构
java.lang.Throwable 顶级父类
|—–java.lang.Error:一般不编写针对性的代码进行处理
|—–java.lang.Exception:可以进行异常的处理
|—–编译时异常(checked)
|—–IOException
|—–FileNotFoundException
|—–ClassNotFoundException
|—–运行时异常(unchecked,RuntimeException)
|—–NullPointerException
|—–ArrayIndexOuntOfBoundsException
|—–ClassCastException
|—–NumberFormatException
|—–InputMismatchException
|—–ArithmeticException
面试题:常见的异常都有哪些?举例说明
package test9;
import java.io.File;
import java.io.FileInputStream;
import java.util.Date;
import java.util.Scanner;
import org.junit.Test;
public class ExceptionTest {
//*****************以下是编译时异常*******************
@Test
public void test7() {
// File file = new File("hello.txt");
// FileInputStream fis = new FileInputStream(file);
//
// int data = fis.read();
// while(data != -1) {
// System.out.println((char)data);
// data = fis.read();
// }
//
// fis.close();
}
//*****************以下是运行时异常*******************
//NullPointerException 空指针异常
@Test
public void test1() {
// int[] arr = null;
// System.out.println(arr[3]);
String str = "abc";
str = null;
System.out.println(str.charAt(0));
}
//IndexOuntOfBoundsException 角标越界
@Test
public void test2() {
//ArrayIndexOuntOfBoundsException
// int arr[] = new int[3];
// System.out.println(arr[3]);
//StringIndexOuntOfBoundsException
String str = "abc";
System.out.println(str.charAt(3));
}
//ClassCastException 类型转换异常
@Test
public void test3() {
Object obj = new Date();
String str = (String)obj;
}
//NumberFormatException 数字转换异常
@Test
public void test4() {
String str = "123";
str = "abc";
int num = Integer.parseInt(str);
}
//InputMismatchException 输入不匹配
@Test
public void test5() {
Scanner sca = new Scanner(System.in);
int score = sca.nextInt();
System.out.println(score);
sca.close();
}
//ArithmeticException 算术异常
@Test
public void test6() {
int a = 10;
int b = 0;
System.out.println(a / b);
}
}
二、异常的处理:抓抛模型
过程一:“抛”:程序在正常执行过程中,一旦出现异常,就会在异常代码处生成一个对应异常类的对象。
并将此对象抛出。
一旦抛出对象以后,其后的代码就不再执行。
关于异常对象的产生:① 系统自动生成的异常对象
②手动的生成一个异常对象,并抛出(throw)
过程二:“抓”:可以理解为异常的处理方式:① try-catch-finally ② throws
三、try-catch-finally的使用
try{
//可能出现异常的代码
}catch(异常类型1 变量名1){
//异常的处理方式1
}catch(异常类型2 变量名2){
//异常的处理方式2
}catch(异常类型3 变量名3){
//异常的处理方式3
}
...
finally{
//一定会执行的代码
}
说明:
1.finally是可选的
2.使用try将可能出现异常代码包装起来,在执行过程中,一旦出现异常,就会生成一个对应异常类的对象,根据此对象
的类型,去catch中进行匹配
3.一旦try中的异常对象匹配到某一个catch时,就进入catch中进行异常的处理。一旦处理完成,就跳出当前的
try-catch结构(在没有写finally的情况)。继续执行其后的代码
4.catch中的异常类型如果没有子父类关系,则谁声明在上,谁声明在下无所谓。
catch中的异常类型如果满足子父类关系,则要求子类一定声明在父类的上面。负责,报错
5.常见的异常处理的方式:① String getMessage() ② printStackTrace() 常用
6.在try结构中声明的变量,在出了try结构以后,就不能再被调用
7.try-catch-finally结构可以相互嵌套
体会1:使用处理编译时异常,是得程序在编译时就不再报错,但是运行时仍可能报错。
相当于我们使用try-catch-finally将一个编译时可能出现的异常,延迟到运行时出现。
体会2:开发中,由于运行时异常比较常见,所以我们通常就不针对运行时异常编写try-catch-finally了。
针对于编译时异常,我们说一定要考虑异常的处理。
package test9;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import org.junit.Test;
public class ExceptionTest1 {
@Test
public void test2() {
try {
File file = new File("hello.txt");
FileInputStream fis = new FileInputStream(file);
int data = fis.read();
while(data != -1) {
System.out.println((char)data);
data = fis.read();
}
fis.close();
}catch(FileNotFoundException e) {
e.printStackTrace();
}catch(IOException e) {
e.printStackTrace();
}
}
@Test
public void test1() {
String str = "123";
str = "abc";
try {
int num = Integer.parseInt(str);
System.out.println("hello-----1");
}catch(NullPointerException e) {
System.out.println("出现空指针异常了,不要着急....");
}catch(NumberFormatException e) {
// System.out.println("出现数值转换异常了,不要着急....");
// 常用的异常处理的两种方式
//一、String getMessage();
// System.out.println(e.getMessage());
//二、printStackTrace():
e.printStackTrace();
}catch(Exception e) {
System.out.println("出现异常了,不要着急....");
}
// System.out.println(num);
System.out.println("hello-----2");
}
}
try-catch-finally中finally的使用:
1.finally是可选的
2.finally中声明的是一定会被执行的代码。即使catch中又出现异常了,try中有return语句,catch中有
return语句等情况。
3.像数据库连接、输入输出流、网络编程Socket等资源,JVM是不能自动的回收的,我们需要自己手动的进行资源
释放。此时的资源释放,就需要声明在finally中。
package test9;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import org.junit.Test;
public class FinallyTest {
@Test
public void test2() {
FileInputStream fis = null;
try {
File file = new File("hello.txt");
fis = new FileInputStream(file);
int data = fis.read();
while(data != -1) {
System.out.println((char)data);
data = fis.read();
}
// fis.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
if(fis != null)
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Test
public void testMethod() {
int num = method();
System.out.println(num);
}
public int method() {
try {
int[] arr = new int[10];
System.out.println(arr[10]);
return 1;
}catch(ArrayIndexOutOfBoundsException e) {
e.printStackTrace();
return 2;
}finally {
System.out.println("我一定会被执行");
return 3;
}
}
@Test
public void test1() {
try {
int a = 10;
int b = 0;
System.out.println(a / b);
}catch(ArithmeticException e) {
// e.printStackTrace();
int[] arr = new int[10];
System.out.println(arr[10]);
}catch(Exception e) {
e.printStackTrace();
}
// System.out.println("我好帅啊!!!");
finally {
System.out.println("我好帅啊");
}
}
}
四、异常处理的方式二:throws + 异常类型
1.”throws + 异常类型”写在方法的声明处。指明此方法执行时,可能会抛出的异常类型。
一旦当方法体执行时,出现异常,仍会在异常代码处生成一个异常类的对象,此对象满足
throws后异常类型时,就会被抛出。异常代码后续的代码,就不再执行!
2.体会:try-catch-finally:真正的将异常给处理掉了。
throws的方式只是将异常抛给了方法的调用者。并没
有真正将异常处理掉。
3.开发中如何选择使用try-catch-finally 还是使用throws?
3.1如果父类中被重写的方法没有throws方式处理异常,则子类重写
的方法也不能使用throws,意味着如果子类重写的方法有异常,
必须使用try-catch-finally方式处理。
3.2执行的方法中,先后调用了另外的几个方法,这几个方法是递进关
执行的。我们建议这几个方法使用throws的方式进行处理。而执
行的方法a可以考虑用try-catch-finally方式进行处理。
package test9;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
public class ExceptionTest2 {
public static void main(String[] args) {
try {
method2();
}catch(FileNotFoundException e) {
e.printStackTrace();
}catch(IOException e) {
e.printStackTrace();
}
// method3();
}
public static void method3() {
try {
method2();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void method2() throws IOException {
method1();
}//IOException是FileNotFoundException的父类,可以省略
public static void method1() throws FileNotFoundException,IOException {
File file = new File("hello.txt");
FileInputStream fis = new FileInputStream(file);
int data = fis.read();
while(data != -1) {
System.out.println((char)data);
data = fis.read();
}
fis.close();
}
}
五、如何自定义异常类?
1.继承于现有的异常结构:RuntimeException、Exception
2.提供提供全局常量serialVersionUID
3.提供重载的构造器
public class MyException extends RuntimeException{
static final long serialVersionUID = -7034897193246939L;
public MyException() {
}
public MyException(String msg) {
super(msg);
}
}
六、子类重写父类异常方法
方法重写的规则之一:
子类重写的方法抛出的异常类型不大于父类被重写的方法抛出的异常类型
package test9;
import java.io.FileNotFoundException;
import java.io.IOException;
public class OverrideTest {
public static void main(String[] args) {
OverrideTest test = new OverrideTest();
test.display(new SubClass());
}
public void display(SuperClass s) {
try {
s.method();
} catch (IOException e) {
e.printStackTrace();
}
}
}
class SuperClass{
public void method() throws IOException{
}
}
class SubClass extends SuperClass{
public void method() throws FileNotFoundException{
}
}
七、手动抛出异常
package test9;
public class StudentTest {
public static void main(String[] args) {
try {
Student s = new Student();
s.regist(-1001);
System.out.println(s);
} catch (Exception e) {
// e.printStackTrace();
System.out.println(e.getMessage());
}
}
}
class Student{
int id;
public void regist(int id) {
if(id > 0) {
this.id = id;
}else {
// System.out.println("你输入的数据非法!");
//手动抛出异常对象
// throw new RuntimeException("你输入的数据非法!");
// throw new Exception("你输入的数据非法!");
throw new MyException("不能输入负数");
}
}
@Override
public String toString() {
return "Student [id=" + id + "]";
}
}
今天的文章java基础教程完整版_java基础知识点整理分享到此就结束了,感谢您的阅读。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/75859.html