一、Java数据类型
1.1 一般的整型变量默认为int,所以long型需要加L或l;一般的浮点型变量默认为double,所以float型需要加F或f;
1.2 自动类型转换
(1)byte->short,char->int->long->float->double可自动类型转换;反方向须强制类型转换
(2)char/byte/short参与运算后,结果为int型。【byte、short、char在储存前会转换为int,boolean也被转换为int,0表示false,非0表示true】
package com.fupng3.str;
public class CharDemo {
public static void main(String[] args) throws Exception {
byte chr='A';
short n=2;
//若m申明为非int型,则编译报错
short m1=n+chr;//编译报错
int m2=n+chr;
}
}
1.3 char型2个字节长度,为什么可以表示汉字?
char型只能表示unicode编码范围在\u0000至\uffff之间的汉字,超过2个字节的无法表示,如“𣡕”
package com.fupng3.str;
public class CharDemo {
public static void main(String[] args) throws Exception {
char chr1='A';
char chr2='我';
char chr3='\uD84E\uDC55';//对应汉字𣡕,该行编译报错
}
}
1.4 默认值问题
(1)局部变量不会默认初始化,只有类的属性才会默认初始化
(2)局部变量和属性的区别
属性 | 局部变量 | |
定义位置 | 类的{}中 | 方法体或形参 |
权限修饰符 | private/默认/protected/public | 无 |
默认初始化 | new对象时,各属性进行默认初始化 | 不进行默认初始化 |
存放位置 | 堆/常量池 | 栈 |
1.5 ==/equals
(1)==:基本数据类型比较值是否相等;引用类型默认用于比较地址是否相等
//Object类equals方法,用于比较地址值是否相等(所有引用类型默认继承Object)
public boolean equals(Object obj) {
return (this == obj);
}
(2)equals默认同==【equals方法不能用于比较基本数据类型】
//Object类中equals源码
public boolean equals(Object obj) {
return (this == obj);
}
(3)某些类会重写equals方法,用于比较值是否相等,如String、Date、ArrayList
//String类的equals方法
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = value.length;
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}
1.6 向上/向下转型【引用类型的类型转换,区别与基本数据类型】
(1)向上转型<多态>:子类调用父类的属性或方法。【自动类型转换】
(2)向下转型:父类调用子类的属性或方法。【强制类型转换,且为父子类关系】
(3)java中继承关系的父子类,相同的方法会被重写,相同的变量没有重写之说,即:如果子类声明了跟父类一样的变量,那意谓着子类中将有两个相同名称的变量,可以通过super.X访问父类中同名变量
子类可以直接赋值给父类对象;
父类赋值给子类需要强制转换
1.7 包装类
(1)8中基本数据类型都有对应的包装类,包装类的目的是使基本数据类型与类能相互转换(包装类使基本数据类型能有类的属性,类能参与运算),如java集合类中,只能使用包装类
(2)基本数据类型、包装类、String的相互转换
(3)Integer中有内部类IntegerCache,用于缓存-128至127之间的数据
package com.fupng3.wrapper;
public class TestBz {
public static void main(String[] args) {
int int1 = 12;
int int2 = 12;
System.out.println(int1==int2);//true,基本数据类型比较值
Integer integer1 = new Integer(12);
Integer integer2 = new Integer(12);
System.out.println(int1==integer1);//true,自动拆箱,当Integer与int进行==比较时,Integer就会拆箱成一个int类型
System.out.println(integer1==integer2);//false,2个new的对象,在堆中地址不同
Integer a1 = 12; //或者写成Integer a1 = Integer.valueOf(12);
Integer a2 = 12;//或者写成Integer a2 = Integer.valueOf(127);
System.out.println(integer2==a1);//false,integer2在堆中,a1在常量池
System.out.println(a1==a2);//true,Integer a1 = 12这种方式定义,相当于valueof方法获取,如果值在-128至127之间,则在常量池中取,反之new
Integer a3 = 200;
Integer a4 = 200;
System.out.println(a3==a4);//false
}
}
(4)Integer.valueof方法源码
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
(5)面试题:Integer类会进行缓存吗?
- 通过new Interger()创建Interger对象,每次返回全新的Integer对象
- 通过Interger.valueOf()创建Interger对象,如果值在-128到127之间,会返回缓存的对象(初始化时)。
二、方法及重载与重写
定义方法格式: 权限修饰符 返回值 函数名(形参) 异常;
(1)函数重载须满足:一同+三不同(三不同种满足其一即可)
(2)方法重写须满足:
(a)更好的访问:权限修饰符不小于父类
(b)有兼容的返回:返回类型若为基本数据类型,则重写方法返回类型不可变;返回类型若为引用数据类型,则重写方法返回类型为该类或该类子类;
(c)同名同形参;
(d)不能比父类抛出更多的异常。
(3)注意点
(a)重载与重写的区别与联系:方法的重载和重写都是实现多态的方式,区别在于前者实现的是编译时的多态性(类内的多态性),而后者实现的是运行时的多态性(父子类间的多态性<重写是对父类方法的重定义>)。
(b)构造函数须与类同名+重写是对父类方法的重定义,所以:构造函数可以重载,构造函数不可以重写
2.1 方法重写
2.1.1 一同三不同
(1)方法名相同
(2)参数个数不同
(3)参数类型不同
(4)参数顺序不同
2.1.2 举例
(1) 方法重载例子
package com.fuping3.ioc;
public class UserDao{
public void ov(String name){
System.out.println("1");
}
private void ov(String name,int age){
System.out.println("2");
}
public int ov(int age,String name){
System.out.println("3");
return 3;
}
}
(2) 非方法重载例子
//权限修饰符不同
public void ov(String name){
System.out.println("1");
}
private void ov(String name){
System.out.println("1");
}
//返回值不同
public void ov(int age,String name){
System.out.println("3");
}
public int ov(int age,String name){
System.out.println("3");
}
//不同方法名
public void ov(int age,String name){
System.out.println("3");
}
public int ov2(int age,String name){
System.out.println("3");
}
//抛出不同异常
public int ov2(int age,String name){
System.out.println("3");
return 3;
}
public int ov2(int age,String name) throws Exception{
System.out.println("3");
return 3;
}
三、可变形参与数组形参
3.1 联系
可变形参类似于数组
3.2 区别
(1)可变形参可传可不传(不传值时:不为空且长度为0),数组形参一定要传;
(2)可变形参只能有一个且在最后
3.3 举例
package com.fuping3.aop;
public class AopTestDemo {
public static void main(String[] args) {
aa("1",2,new String[]{"3","4"});
aa("5",6);
System.out.println("*********");
bb("1",2,new String[]{"3","4"});
//bb("5",6);//编译报错:形参为数组时,不传会编译不通过
}
public static void aa(String i,int j,String ...k){
System.out.println(i);
System.out.println(j);
//未传可变参数时,k.length等于0
for(int m=0;m< k.length;m++){
System.out.println(k[m]);
}
}
public static void bb(String i,int j,String[] k){
System.out.println(i);
System.out.println(j);
for(int m=0;m< k.length;m++){
System.out.println(k[m]);
}
}
}
四、java异常体系
- Throwable的子类为Error和Exception
- error表示系统级的错误,是java运行环境内部错误或者硬件问题,不能指望程序来处理这样的问题,除了退出运行外别无选择,它是Java虚拟机抛出的。例如当 JVM 不再有继续执行操作所需的内存资源时,将出现 OutOfMemoryError。
- Exception的子类为RuntimeException异常(非受检异常)和RuntimeException以外的异常(受检异常)。
- 受检异常,JVM要求我们必须对其进行cathc处理,所以,面对这种异常,不管我们是否愿意,都是要写一大堆的catch块去处理可能出现的异常。
- RuntimeException异常就是应用程序运行时,可能会抛出的异常。这些异常是非受检异常,编译时Java编译器不会去检查,不会强制程序员添加处理异常的代码。程序中可以选择捕获处理,也可以不处理。
出现运行时异常的时候,程序会由虚拟机接管,程序会将异常一直向上抛,一直抛到遇到处理代码。
如果没有catch块进行处理,到了最上层,如果是多线程就由Thread.run()抛出,该线程终止;如果是主程序,就由main.run()抛出,主程序终止。
4.1 Java的异常处理是通过5个关键词来实现的:
try:用来指定一块预防所有异常的程序
catch:紧跟在try后面,用来捕获异常
throw:用来明确的抛出一个异常
throws:用来标明一个成员函数可能抛出的各种异常
finally:确保一段代码无论发生什么异常都会被执行的一段代码。
面试题:final、finally、finalize的区别
(1)、final用于声明变量、方法和类的,分别表示变量值不可变,方法不可覆盖,类不可以继承
(2)、finally是异常处理中的一个关键字,表示finally{}里面的代码一定要执行
(3)、finalize是Object类的一个方法,在垃圾回收的时候会调用被回收对象的此方法。