1 重载和重写的区别
重载: 发生在同一个类中,方法名必须相同(同名不同参),参数类型不同,个数不同,顺序不同,方法返回值和访问修饰符可以相同也可以不同,发生在编译时。
重写: 发生在父子类中,方法名,参数列表必须相同,返回值范围小于等于父类,抛出的异常范围小于等于父类,访问修饰符范围大于等于父类;如果父类方法访问修饰符为 private 则子类就不能重写该方法。
2 String和StringBuffer,StringBuilder 的区别是什么?String 为什么是不可变的?
可变性
简单的来说:String 类中使用 final 关键字字符数组保存字符串, private final char value[] ,所以 String对象是不可变的。而StringBuilder 与 StringBuffer 都继承自 AbstractStringBuilder 类,在AbstractStringBuilder中也是使用字符数组保存字符串 char[]value 但是没有用 final 关键字修饰,所以这两种对象都是可变的。
线程安全性
String 中的对象是不可变的,也就可以理解为常量,线程安全。StringBuffer 对方法加了同步锁或者对调用的方法加了同步锁,所以是线程安全的。StringBuilder 并没有对方法进行加同步锁,所以是非线程安全的。
性能
每次对 String 类型进行改变的时候,都会生成一个新的 String 对象,然后将指针指向新的 String 对象。
StringBuffer 每次都会对 StringBuffer 对象本身进行操作,而不是生成新的对象并改变对象引用。相同情况下使用StirngBuilder 相比使用 StringBuffer 仅能获得 10%~15% 左右的性能提升,但却要冒多线程不安全的风险。
对于三者使用的总结:
1. 操作少量的数据 => 使用String
2. 单线程操作字符串缓冲区下操作大量数据 => 使用StringBuilder
3. 多线程操作字符串缓冲区下操作大量数据 => 使用StringBuffer
3. 接口和抽象类的区别是什么
相同点:
(1)都不能被实例化
(2)接口的实现类或抽象类的子类都只有实现了接口或抽象类中的方法后才能实例化。需要实现的抽象方法,否则它必须是一个抽象类。
不同点:
(1)接口只有定义,不能有方法的实现(常量,抽象方法)(jdk7及其以前),java 1.8中可以定义default方法体和静态方法 私有方法(jdk9)。,而抽象类可以有定义与实现。
(2)定义接口interface,实现接口的关键字为implements(in 亏们ci);定义抽象类abstract关键字修饰,继承抽象类的关键字为extends(A 可死den si),一个类可以实现多个接口,但一个类只能继承一个抽象类。所以,使用接口可以间接地实现多重继承。
(3)接口强调特定功能的实现,而抽象类强调所属关系。
(4)接口成员变量默认为public static final,必须赋初值,不能被修改;
抽象方法默认修饰符是 public abstract 供子类重写(没有方法体);
默认方法public default供实现类继承的,
静态方法 默认修饰符 public static(只供接口直接调用,实现类继承不了);
私有方法 修饰符 private只能在接口中直接调用,实现类继承不了。
抽象类中成员变量默认default,可在子类中被重新定义,也可被重新赋值;
- 额外的功能---> 在接口中定义,让实现类实现
- 共性的功能---> 在父类中定义,让子类继承
什么时候会定义抽象方法:
当父类中的某个方法,所有的子类都有不同的实现的时候,父类中的这个方法就定义成抽象方法
4.手写冒泡排序?
冒泡排序核心思路:每次将相邻的两个元素继续比较,大的往后放(相邻的两个元素j和j+1)
冒泡排序核心思路:每次将相邻的两个元素继续比较
如下图所示:
第一轮比较 3次
第二轮比较 2次
第三轮比较 1次
public class Test1 {
public static void main(String[] args) {
// 1、准备一个数组
int[] arr = {5, 2, 3, 1};
// 2、定义一个循环控制排几轮
for (int i = 0; i < arr.length - 1; i++) {
// i = 0 1 2 【5, 2, 3, 1】 次数
// i = 0 第一轮 0 1 2 3
// i = 1 第二轮 0 1 2
// i = 2 第三轮 0 1
// 3、定义一个循环控制每轮比较几次。
for (int j = 0; j < arr.length - i - 1; j++) {
// 判断当前位置的元素值,是否大于后一个位置处的元素值,如果大则交换。
if(arr[j] > arr[j+1]){
int temp = arr[j + 1];
arr[j + 1] = arr[j];
arr[j] = temp;
}
}
}
System.out.println(Arrays.toString(arr));
}
}
5. 在 java 中 wait 和 sleep 方法的不同?
最大的不同是在等待时 wait 会释放锁,而 sleep 一直持有锁。wait 通常被用于线程间交互,sleep 通常被用于暂停执行。
6.JDK_JRE_JVM的组成和作用
JVM: Java虚拟机,是专门用来运行Java程序的,但是不能单独安装
JRE: Java运行环境,包含JVM(Java虚拟机,是专门用来运行Java程序的)和核心类库
JDK: Java开发工具包,包含JRE和开发工具
小贴士:
三者关系: JDK > JRE > JVM
7.常量(整数常量、小数常量、字符常量、布尔常量、字符串常量、空常量)
1.概念:在程序的执行过程中,其值不可以发生改变的量
2.分类:
(1)整数常量: 100 200
(2)小数常量: 5.5 7.7
(3)字符常量:
java中规定字符常量必须使用单引号''引起来,而且单引号''中只能写一个字符(不能不写,也不能写2个以上)
举例:
A: 'a' 正确的
B: '' 里面什么都没有写 错误的
C: ' ' 里面有一个空格 正确的
D: 'ab' 错误的
E: '好' 正确的
F: '女子' 错误的
(4)布尔常量:只有两个值true和false
true: 表示肯定的,对的,是的,正确的,成立的
false:表示否定的,错的,不是的,却无的,不成立的
(5)字符串常量:
java中规定字符串常量必须使用双引号""引起来,而且单引号""中可以写多个字符(0个,1个,2个....)
举例:
A: "a" 正确的
B: "" 里面什么都没有写 正确的
C: " " 里面有一个空格 正确的
D: "ab" 正确的
E: "好" 正确的
F: "女子" 正确的
(6)空常量: null System.out.println(null);//错误: 不能直接打印空常量null
快捷键: ctrl + d 复制一行
8.变量(byte、short、int、long、float、double、char、boolean)
1.变量概念: 在程序的执行过程中,其值可以在一定范围内发生改变的量(容器:里面只能放一个数据)
2.分类:
(1)整数
byte 1个字节 -128到127
short 2个字节 正负3万多
int 4个字节 正负21亿 整数默认int类型
long 8个字节 大概19位数字 表示long类型数据后面需要加L/l
(2)小数
float 4个字节 表示float数据后面需要加F/f
注意: 虽然float占4个字节,但是由于采用科学计数法,取值范围远远超过long
double 8个字节 小数默认double类型
(3)字符:
char 2个字节
(4)布尔:
boolean 1个字节 取值为true或者false
9.标识符的含义及注意事项
1.概念: 程序中起名字的地方(类名,方法名称,变量名)
2.命名规则: 硬 性 要 求
标识符可以包含 英文字母26个(区分大小写) 、 0-9数字 、 $(美元符号) 和 _(下划线) 。
标识符不能以数字开头。
标识符不能是关键字。
3.命名规范: 软 性 建 议
类名规范:首字母大写,后面每个单词首字母大写(大驼峰式)。
Demo01BianLiang
方法名规范: 首字母小写,后面每个单词首字母大写(小驼峰式)。
getMin(...){...}
变量名规范:首字母小写,后面每个单词首字母大写(小驼峰式)。
maxValue
10.ASCII码表
计算机是一个二货,只能存储0和1,所以存储到计算机中的所有内容都会转换成0和1进行存储
所以我们在计算机中存储的字符也不例外,也需要把字符转换成0和1进行存储
存储字符时:需要查找ASC码表,找到字符对应的数字,将数字转换为二进制数存放到计算机中
'A' ---> 65 ---> 1000001 大写字母是连续的,ASCII编码值依次+1
'a' ---> 97 ---> 1100001 小写字母是连续的,ASCII编码值依次+1
'0' ---> 48 ---> 110000 数字字符是连续的,ASCII编码值依次+1
11.方法
方法的格式:
修饰符 返回值类型 方法名称(数据类型1 变量名称1,数据类型2 变量名称2...) {
功能代码;
return ;//如果返回值类型是void,建议省略不写,有数据不能省略
}
三要素:
(1)方法名称: printOu
(2)参数列表: int num
(3)返回值类型: void
return ;
a.结束方法
b.返回到方法的调用处
形式参数和实际参数
12.面向对象理解
编程思想其实就是编程思路,我们开发中2种经典的编程思想就是面向过程编程思想和面向对象编程思想.
面向过程编程思想
- 强调的是过程,必须清楚每一个步骤,然后按照步骤一步一步去实现
面向对象编程思想
- 强调的是对象, 通过调用对象的行为来实现功能,而不是自己一步一步的去操作实现。
举例对比2种编程思想
- 洗衣服:
- 面向过程:把衣服脱下来-->找一个盆-->放点洗衣粉-->加点水-->浸泡10分钟-->揉一揉-->清洗衣服-->拧干-->晾起来
- 面向对象: 把衣服脱下来-->给女朋友去洗
- 吃饭
- 面向过程: 买菜--->洗菜--->炒菜--->吃
- 面向对象: 找个饭店-->10块钱
13.成员变量和局部变量的区别
- 类中位置不同:成员变量(类中方法外)局部变量(方法内部或方法声明上)
- 内存中位置不同:成员变量(堆内存)局部变量(栈内存)
- 生命周期不同:成员变量(随着对象的存在而存在,随着对象的消失而消失)局部变量(随着方法的调用而存在,随着方法的调用完毕而消失)
- 初始化值不同:成员变量(有默认初始化值)局部变量(没有默认初始化值,必须先定义,赋值才能使用)
14.封装
- 是面向对象三大特征之一(封装,继承,多态)
- 是面向对象编程语言对客观世界的模拟,客观世界里成员变量都是隐藏在对象内部的,外界是无法直接操作的
封装原则
- 将类的某些信息隐藏在类内部,不允许外部程序直接访问,而是通过该类提供的方法来实现对隐藏信息的操作和访问
- 例如:成员变量使用private修饰,提供对应的getXxx()/setXxx()方法
封装好处
- 通过方法来控制成员变量的操作,提高了代码的安全性
- 把代码用方法进行封装,提高了代码的复用性
15.继承
为什么要有继承
现实生活中,为什么要有继承?
程序中为什么要有继承?
继承:在java中指的是“一个类”可以“继承自”“另一个类”。 "被继承的类"叫做: 父类/超类/基类,"继承其他类的类"叫做:子类。继承后,“子类”中就“拥有”了“父类”中所有的成员(成员变量、成员方法)。 “子类就不需要再定义了”。
继承的好处
- 提高代码的复用性(减少代码冗余,相同代码重复利用)。
- 使类与类之间产生了关系。
继承的格式
通过 extends 关键字,可以声明一个子类继承另外一个父类,定义格式如下:
class 父类 {
...
}
class 子类 extends 父类 {
...
}
需要注意:Java是单继承的,一个类只能继承一个直接父类,并且满足is-a的关系,例如:Dog is a Animal
继承后构造方法的访问规则
- 构造方法不能被继承
继承后私有成员的访问规则
- 父类的“私有成员”可以被子类继承,但子类不能被直接访问。
继承后非私有成员的访问规则
- 当通过“子类”访问非私有成员时,先在子类中找,如果找到就使用子类的,找不到就继续去“父类”中找。
16.多态
生活中,比如跑的动作,小猫、小狗和大象,跑起来是不一样的。再比如飞的动作,昆虫、鸟类和飞机,飞起来也是不一样的。可见,同一行为,通过不同的事物,可以体现出来的不同的形态。多态,描述的就是这样的状态。
定义
- 多态: 是指同一行为,对于不同的对象具有多个不同表现形式。
- 程序中多态: 是指同一方法,对于不同的对象具有不同的实现.
前提条件【重点】
- 继承或者实现【二选一】
- 父类引用指向子类对象【格式体现】 Fu fu = new Zi();
- 方法的重写【意义体现:不重写,无意义】
多态的好处和弊端
- 实际开发的过程中,父类类型作为方法形式参数,传递子类对象给方法,进行方法的调用,更能体现出多态的扩展性与便利。但有好处也有弊端
- 好处
- 提高了代码的扩展性
- 弊端
- 多态的情况下,只能调用父类的共性内容,不能调用子类的特有内容。
引用类型转换
向上转型
- 子类类型向父类类型向上转换的过程,这个过程是默认的。
向下转型(可以访问 子类独有的功能,解决多态的弊端)
- 父类类型向子类类型向下转换的过程,这个过程是强制的。
instanceof关键字:向下强转有风险,最好在转换前做一个验证 :
变量名 instanceof 数据类型
如果变量属于该数据类型,返回true。
如果变量不属于该数据类型,返回false。
if( anl instanceof Cat){//判断anl是否能转换为Cat类型,如果可以返回:true,否则返回:false
Cat c = (Cat)anl;//安全转换
}
多态的应用场景:变量多态、形参多态、返回值多态
16.static关键字
static是一个静态修饰符关键字,表示静态的意思,可以修饰成员变量和成员方法以及代码块。
static修饰成员变量
当 static 修饰成员变量时,该变量称为类变量。该类的每个对象都共享同一个类变量的值。任何对象都可以更改该类变量的值,但也可以在不创建该类的对象的情况下对类变量进行操作。
对象名.静态成员变量名;
类名.静态成员变量名;
static修饰成员方法
- 被static修饰的方法会变成静态方法,也称为类方法,该静态方法可以使用类名直接调用。
对象名.方法名(实参);
类名.方法名(实参); 推荐
静态方法调用的注意事项:
- 静态方法中不能出现this关键字
- 静态方法中只能直接访问静态成员变量和静态成员方法(main方法也是static修饰的)
- 静态方法中不能直接访问非静态成员变量和非静态成员方法
- 非静态方法中可以直接访问一切成员变量和成员方法
static修饰代码块
- 被static修饰的代码块,就叫做静态代码块
定义和执行
- 位置:类中方法外。
- 执行:随着类的加载而执行且执行一次,优先于构造方法的执行。
- 注意: 如果是main所在的类中的静态代码块,会优先main方法执行
- 使用场景: 例如加载驱动,也就是只需要执行一次的代码就可以放在静态代码块中
17.内部类
将一个类A定义在另一个类B里面,里面的那个类A就称为内部类,B则称为外部类。
成员内部类
- 成员内部类 :定义在类中方法外的类。
访问特点
- 内部类可以直接访问外部类的成员,包括私有成员。
- 外部类要访问内部类的成员,必须要建立内部类的对象。
创建内部类对象格式:
外部类名.内部类名 对象名 = new 外部类型().new 内部类型();
匿名内部类
- 匿名内部类 :是内部类的简化写法。它的本质是一个带具体实现的 父类或者父接口的 匿名的 子类对象。
18. 自动装箱与拆箱
Java提供了两个类型系统,基本类型与引用类型,使用基本类型在于效率,然而很多情况,会创建对象使用,因为对象可以做更多的功能,如果想要我们的基本类型像对象一样操作,就可以使用基本类型对应的包装类
装箱:将基本类型用它们对应的引用类型包装起来;
拆箱:将包装类型转换为基本数据类型;
由于我们经常要做基本类型与包装类之间的转换,从Java 5(JDK 1.5)开始,基本类型与包装类的装箱、拆箱动作可以自动完成。
19. == 与 equals
== : 它的作用是判断两个对象的地址是不是相等。即: 判断两个对象是不是同一个对象。(基本数据类型==比较的是值,引用数据类型==比较的是内存地址)。
equals() : 它的作用也是判断两个对象是否相等。但它一般有两种使用情况,如下:
情况1:类没有覆盖 equals() 方法。则通过 equals() 比较该类的两个对象时,等价于通过“==”比较这两个对象。
情况2:类覆盖了 equals() 方法。一般,我们都覆盖 equals() 方法来两个对象的内容相等;若它们的内容相等,则返回 true (即,认为这两个对象相等)。
说明:
String 中的 equals 方法是被重写过的,因为 object 的 equals 方法是比较的对象的内存地址,而 String 的equals 方法比较的是对象的值。
当创建 String 类型的对象时,虚拟机会在常量池中查找有没有已经存在的值和要创建的值相同的对象,如果有就把它赋给当前引用。如果没有就在常量池中重新创建一个 String 对象。
public class test1 {
public static void main(String[] args) {
String a = new String("ab"); // a 为一个引用
String b = new String("ab"); // b为另一个引用,对象的内容一样
String aa = "ab"; // 放在常量池中
String bb = "ab"; // 从常量池中查找
if (aa == bb) { // true
System.out.println("aa==bb");
}
if (a == b) { // false,非同一对象
System.out.println("a==b");
}
if (a.equals(b)) { // true
System.out.println("aEQb");
}
if (42 == 42.0) { // true
System.out.println("true");
}
}
}
20. 关于final关键字的一些总结
final: 不可改变。可以用于修饰类、方法和变量。
- 类:被修饰的类,不能被继承。
- 方法:被修饰的方法,不能被重写。
- 变量:被修饰的变量,就只能赋值一次,不能被重新赋值。
查询API发现像 public final class String 、public final class Math 、public final class Scanner 等,很多我们学习过的类,都是被final修饰的,目的就是供我们使用,而不让我们所以改变其内容。
局部变量——引用类型
引用类型的局部变量,被final修饰后,只能指向一个对象,地址不能再更改。但是不影响对象内部的成员变量值的修改,代码如下:
成员变量
成员变量涉及到初始化的问题,初始化方式有两种,只能二选一:
显示初始化:
public class FinalVariable {
final int NUM1 = 10;
}
构造方法初始化:
public class FinalVariable {
final int NUM2;
public FinalVariable(int NUM2){
this.NUM2 = NUM2;
}
public FinalVariable(){
this.NUM2 = 10;
}
}
被final修饰的常量名称,一般都有书写规范,所有字母都大写。
21. 接口和抽象类的区别是什么(必会)
相同点:
(1)都不能被实例化
(2)接口的实现类或抽象类的子类都只有实现了接口或抽象类中的方法后才能实例化。需要实现的抽象方法,否则它必须是一个抽象类。
不同点:
(1)接口只有定义,不能有方法的实现(常量,抽象方法)(jdk7及其以前),java 1.8中可以定义default方法体和静态方法 私有方法(jdk9)。,而抽象类可以有定义与实现。
(2)定义接口interface,实现接口的关键字为implements(in 亏们ci);定义抽象类abstract关键字修饰,继承抽象类的关键字为extends(A 可死den si),一个类可以实现多个接口,但一个类只能继承一个抽象类。所以,使用接口可以间接地实现多重继承。
(3)接口强调特定功能的实现,而抽象类强调所属关系。
(4)接口成员变量默认为public static final,必须赋初值,不能被修改;
抽象方法默认修饰符是 public abstract 供子类重写(没有方法体);
默认方法public default供实现类继承的,
静态方法 默认修饰符 public static(只供接口直接调用,实现类继承不了);
私有方法 修饰符 private只能在接口中直接调用,实现类继承不了。
抽象类中成员变量默认default,可在子类中被重新定义,也可被重新赋值;
- 额外的功能---> 在接口中定义,让实现类实现
- 共性的功能---> 在父类中定义,让子类继承
什么时候会定义抽象方法:
当父类中的某个方法,所有的子类都有不同的实现的时候,父类中的这个方法就定义成抽象方法
22.数据类型转换
自动类型转换【从小到大自动】
取值范围小的数据或者变量可以直接赋值给取值范围大的变量(小萝卜可以直接放入大坑中)
2.特点:
(1)自动类型转换是自动完成的,不需要代码的干预
(2)byte/short/char类型数据,只要参加运算会自动转换为int类型
(3)byte、short、char-->int-->long-->float-->double
总结:
根据需求,在数据前面补充若干字节的0,因为补充的都是0,对原有数据大小是没有影响的(打肿脸充胖子)
强制类型转换【从大到小强制】
1.强制类型转换概念:
取值范围大的数据或者变量不能直接赋值给取值范围小的变量(大萝卜不能直接放入小坑中)
解决方案:
(1)把坑变大
(2)把萝卜变小(强制类型转换)
2.格式:
转后类型 变量名称 = (转后类型)转前数据或者变量;
long类型(8个字节)的数字5:
long num = 5L;
long类型强制类型转换成int类型(4个字节):
int a = (int)num;//把num中的数据强制类型转换成int类型,并把结果赋值给int变量a
根据需求,砍掉数据左侧的若干字节的数据,只要砍掉的都是0,对原数据没有影响
但是只要砍掉的数据中包含1,就会对原数据产生影响(可能会损失精度)
23.自增自减运算符
1.作用: 让变量的值增加1(++)或者减少1(--)
2.使用格式:
(1)可以写在变量的前面: ++a,--a
(2)可以写在变量的后面: a++,a--
3.使用特点:
(1)单独使用: ++/--自己独占一行,没有其它运算一起参与
前++和后++,没有任何区别,都是让变量的值增加1
前--和后--,没有任何区别,都是让变量的值减少1
(2)混合使用: 和其它运算(赋值,打印等)一起
前++/--: 先++/--,后再使用 先给变量的值增加(++)或者减少(--)1,然后再使用++/--后的结果
后++/--: 先使用,然后++/-- 先使用变量的值,再把变量的值 增加(++)或者减少(--)1
24.逻辑运算符
1.作用:
用来连接多个条件(布尔表达式的: 结果为true/false的式子),最终的结果也必须是一个布尔类型的数据,要么是true,要么是false
不管逻辑运算符连接的式子有多么简单或者多么复杂,最终结果要么是true,要么是false
2.分类:
(1)& 逻辑与
(2)|逻辑或
(3)^ 逻辑异或,相同为false,不同为true ----基本不用
(4)!逻辑取反
逻辑运算符的短路效果
逻辑运算符的短路效果
1.短路的逻辑运算符
(1)短路逻辑与&&: 左侧为false,右边不计算
(2)短路逻辑或||: 左侧为true,右侧不计算
2.特点:
(1)短路逻辑与&&: 和&结果是相同的,但是&&可以提高效率
(2)短路逻辑与||: 和|结果是相同的,但是||可以提高效率
3.建议:
以后开发学习中,全部使用短路与&& 以及 短路或||
25.选择结构-switch
1.switch语句的格式:
switch(表达式) {
case 常量值1;
语句体1;
break;
case 常量值2;
语句体2;
break;
...
case 常量值n;
语句体n;
break;
default:
语句体n+1;
break;
}
其它语句;
注意事项:
(1)break的作用是用来结束switch语句的,一旦执行break,直接跳出到switch外面的其它语句继续执行
(2)switch后面()中的表达式的数据类型,只能是以下几种类型:
基本类型: byte/short/char/int 都可以 -----------------重要,选择题经常考到---------------
引用类型: String或者枚举
(3)case 后面只能写常量,而且常量值不能重复
(4)最后一个default的作用:
用来兜底的,如果所有的case后面的常量值和switch中表达式的值都不相同,就执行default中的内容
(5)如果default放在最后的话: 后面的break可以省略
(6)如果所有的case和default后面都有break,那么default和case的顺序可以任意排列,不影响最终的结果
26.循环语句的区别
三种循环的区别总结
1.建议使用的顺序:for,while,do-while
2.循环次数确定的话,建议使用for,循环次数不确定建议使用while 【后面有使用场景】
循环次数不确定需要先写成死循环的格式【while好看】 --------后天讲解
3.do-while循环来讲的话,至少执行一次
4.while和do-while循环而言,循环结束后,初始化条件中定义的变量可以继续使用,
但是for循环的不能使用(在for循环内部定义初始化语句)
死循环
1.概念: 永不休止的循环
2.分类:
(1)for循环的死循环格式 for芬芬
for(;;){...}
(2)while循环的死循环格式 建议使用
while(true){...}
(3)do-while循环的死循环格式
do{
...
}while(true);
选择结构(if、swith)
循环结构(for,while,do-while )
27.循环跳转
break的介绍(不能使用在除switch和循环语句以外的其它位置)
break的使用场景:
1.使用在switch语句中,用来结束switch语句,执行switch语句后面的其它语句
2.使用在循环中,用来结束循环(1.本次循环的循环体中break后面的代码不再执行 2.剩余次数的循环也不再执行),执行循环后面的其它语句
3.break不能使用在出switch和循环语句以外的其它位置
continue的介绍(只能使用在循环中)
continue的使用场景:
1.只能使用在循环中,作用是提前结束本次循环,继续进行下一次循环
2.不能使用在除循环结构中的其它位置
28.数组理解(存储多个数据,但是数据的类型必须一致,长度是不可以发生改变)
数组:
1.概念: java中的数组就是一个容器,可以存储多个数据,但是数据的类型必须一致
2.特点:
(1)可以存储多个数据
(2)多个数据的类型必须保持一致
(3)数组一旦创建,长度是永远不可以发生改变
1.数组变量定义格式一: ---------------推荐使用-------------
数据类型[] 数组名称;
2.数组变量定义格式二:
数据类型 数组名称[];
数组元素有默认值:
1.整数: 0
2.小数: 0.0
3.字符: 空白字符
4.布尔: false
数组原理内存图
一个数组内存图
29.this关键字(使用 this 修饰方法中的变量,解决成员变量被隐藏的问题 )
this的含义和使用
- this含义: this代表当前对象(谁调用this所在的方法,谁就是当前对象)
- this关键字其主要作用是区分同名的局部变量和成员变量
- 方法的形参如果与成员变量同名,不带this修饰的变量指的是形参,而不是成员变量
- 方法的形参没有与成员变量同名,不带this修饰的变量指的是成员变量
- this:存储的“当前对象”的引用;
- this可以访问:本类的成员属性、成员方法、构造方法;
- super:存储的“父类对象”的引用;
- super可以访问:父类的成员属性、成员方法、构造方法;
super的注意事项:
1.super访问成员变量和成员方法: 优先去父类中找,如果有就直接使用,如果没有就去爷爷类中找,如果有,就用,依次类推...
2.子类的构造方法默认会调用父类的空参构造方法,如果父类中的没有空参构造方法,只定义了有参构造方法,会编译报错
30.Object类
- java.lang.Object类是Java语言中的根类,即所有类的父类。如果一个类没有特别指定父类, 那么默认则继承自Object类。
1.toString():返回该对象的字符串表示。
2.equals:指示其他某个对象是否与此对象“相等”。
3.hashCode()方法:公开的,带有native关键字,底层调用C++程序,返回值为int型数字。
hashCode()方法返回的是哈希码:实际上就是一个java对象的内存地址,经过哈希算法,得出的一个值。
4.finalize()方法:finalize()方法只有一个空方法体,里面没有代码,而且这个方法是protected修饰的。
这个方法不需要程序员手动调用,JVM的垃圾回收器(也叫GC)负责调用这个方法。
finalize()方法执行时机:当一个java对象即将被垃圾回收器回收的时候,在对象销毁之前,垃圾回收器先调用这个finalize()方法。
5.notify 方法:唤醒在此对象监视器上等待的单个线程
6.notifyAll 方法:唤醒在此对象监视器上等待的所有线程。
7. wait 方法:导致当前的线程等待(使当前线程等待该对象的锁),当前线程必须是该对象的拥有者,也就是具有该对象的锁。直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法
8.wait(long timeout) 设定一个超时间隔,如果在规定时间内没有获得锁就返回。wait() 方法实际上调用的是 wait(long timeout) 方法,只不过 timeout 为 0,即不等待。
9. wait(long timeout, int nanos) 方法:超过参数 timeout 与 nanos 设置的超时时间。
参数
timeout – 等待时间(以毫秒为单位)。
nanos – 额外等待时间(以纳秒为单位)。timeout 与 nanos 参数都为 0,则不会超时,会一直进行等待,类似于 wait() 方法。
31.基本类型与字符串之间的转换
基本类型转换为String
- 转换方式
- 方式一:直接在数字后加一个空字符串
- 方式二:通过String类静态方法valueOf()
String转换成基本类型
除了Character类之外,其他所有包装类都具有parseXxx静态方法可以将字符串参数转换为对应的基本类型;
32.异常
- 异常 :指的是程序在执行过程中,出现的非正常的情况,最终会导致JVM的非正常停止。
注意: 在Java等面向对象的编程语言中,异常本身是一个类,产生异常就是创建异常对象并抛出了一个异常对象。Java处理异常的方式是中断处理。
异常指的并不是语法错误,语法错了,编译不通过,不会产生字节码文件,根本不能运行.
异常体系
异常机制其实是帮助我们找到程序中的问题,异常的根类是java.lang.Throwable,其下有两个子类:java.lang.Error与java.lang.Exception,平常所说的异常指java.lang.Exception。
Throwable体系:
- Error:严重错误Error,无法通过处理的错误,只能事先避免,好比绝症。(栈内存溢出错误,服务器宕机,数据库崩溃...)
- Exception:表示异常,异常产生后程序员可以通过代码的方式纠正,使程序继续运行,是必须要处理的。好比感冒、阑尾炎。
异常分类
我们平常说的异常就是指Exception,因为这类异常一旦出现,我们就要对代码进行更正,修复程序。
异常(Exception)的分类:根据在编译时期还是运行时期去检查异常?
- 编译时期异常:checked异常。在编译时期,就会检查,如果没有处理异常,则编译失败。(必须处理)(如日期格式化异常)
- 运行时期异常:runtime异常。在运行时期,检查异常.在编译时期,运行异常不会编译器检测(不报错)。(如数学异常)
常见异常:
1) java.lang.NullPointerException 空指针异常;出现原因:调用了未经初始化的对象或者是不存在的对象。
2) java.lang.ClassNotFoundException 指定的类找不到;出现原因:类的名称和路径加载错误;通常都是程序试图通过字符串来加载某个类时可能引发异常。
3) java.lang.NumberFormatException 字符串转换为数字异常;出现原因:字符型数据中包含非数字型字符。
4) java.lang.IndexOutOfBoundsException 数组索引越界异常
5) java.lang.IllegalArgumentException 方法传递参数错误。
6) java.lang.ClassCastException 数据类型转换异常。
7)SQLException SQL 异常,常见于操作数据库时的 SQL 语句错误。
8) java.lang.NoSuchMethodException 方法不存在异常。
异常的产生和处理
throw关键字的作用
在java中,提供了一个throw关键字,它用来抛出一个指定的异常对象。throw用在方法内,用来抛出一个异常对象,将这个异常对象传递到调用者处,并结束当前方法的执行。
声明处理异常
声明处理异常:使用throws关键字将异常标识出来, 表示当前方法不处理异常,而是提醒给调用者, 让调用者来处理....最终会到虚拟机,虚拟机直接结束程序,打印异常信息。
捕获处理异常try…catch
- 捕获处理异常:对异常进行捕获处理 , 处理完后程序可以正常向下执行。
注意:finally不能单独使用。
当只有在try或者catch中调用退出JVM的相关方法,此时finally才不会执行,否则finally永远会执行。
异常注意事项
- 运行时异常被抛出可以不处理。即不捕获也不声明抛出。
- 如果父类的方法抛出了多个异常,子类覆盖(重写)父类方法时,只能抛出相同的异常或者是他的子集。
- 父类方法没有抛出异常,子类覆盖父类该方法时也不可抛出异常。此时子类产生该异常,只能捕获处理,不能声明抛出
- 当多异常分别处理时,捕获处理,前边的类不能是后边类的父类
注意:这种异常处理方式,要求多个catch中的异常不能相同,并且若catch中的多个异常之间有子父类异常的关系,那么子类异常要求在上面的catch处理,父类异常在下面的catch处理