Java基础语法易错知识点总结1-3
文章目录
一、对象创建时的内存细节
1.复制还是类似指针?
先看下面的代码,思考结果。
public class Test {
public static void main(String[] args) {
Book b1 = new Book();
b1.name = "金苹果";
b1.info = "讲述了果农种植金色苹果的辛勤路程。";
b1.say();
Book b2 = b1; //易错点
b2.name = "银苹果";
b1.say();
}
}
class Book {
String name;
String info;
void say(){
System.out.println("书名:"+name+",简介:"+info);
}
}
结果如下:
结果是否和你预期的一样呢,其实关键在于作者加了注释的那一行代码,很多人容易把它理解成复制。但其实不是,b1和b2都只是名称而已,他们指向的是同一个对象,用b2把name修改之后再用b1执行say()的时候输出的是银苹果而不是金苹果。
2.栈、堆和方法区
接下来结合变量名和对象在内存中的存储形式来理解上面的代码。如下图所示:在执行到Book b1系统会将Book类加载到方法区中,同时将Book b1变量存入栈中,在执行到new Book()时系统会将创建的Book对象存储到堆内存中,栈中的b1存放的是Book对象的地址,类似于c语言中的指针。当执行b1.name = "xxxx"和b1.info="xxxx"时系统会根据b1指向的地址去寻找堆中的对象进行修改。当执行Book b2 = b1时只不过是将b1指向的地址赋值给b2而已,所以b1和b2指向的是同一个地址,到这里就能理解上面的执行结果了。当执行b1.say()时系统会调用方法区中的say()方法,执行结束以后栈中的变量依次出栈,由GC线程回收内存中的垃圾。
3.测试
下面的代码请大家自己分析
二、方法的重载和重写
1.重载的条件
1.方法名称相同 ;
2.参数列表的长度或顺序或类型不同;
注意:是否构成重载和返回值类型无关!!!!!
2.重写
(1)子类实例化
子类Student实例化的时候会先创建父类Person的实例,由super关键字指向父类。super可以访问父类的构造方法、方法和属性。用this和super调用其他构造方法必须放在第一行。
(2)重写
1.参数列表、返回值和函数名与被重写方法相同
2.访问权限不能比被重写方法低
3.static和private不能重写,但是能够被再次声明
三、static静态关键字
1.静态修饰的属性
试想如果内存空间的存储情况如下,四个人的地区都是相同的,如果要对地区进行修改需要对4个人依次修改,这个过程十分繁琐,有没有什么简单的方法呢?
其实很简单,只需要用static修饰region就可以了,用static修饰的属性是在类创建的时候就被加载到方法区中了,所有对象指向的方法区中的同一个region。
2.静态修饰的方法
静态修饰的方法可以直接用类名来使用。
需要注意的是,静态资源是在类创建时创建的,而非静态资源是在对象创建时创建的。所以静态资源不能访问非静态资源,而非静态资源可以访问静态资源。
3.对main方法的理解
args数组其实是我们在运行main函数时可以传递进去的一些参数
四、权限修饰符
五、final关键字
可以修饰属性、变量、类、方法
修饰属性、变量:变成常量,无法再次赋值,如果局部变量之前没有赋值,那么可以赋值一次;属性用final修饰必须赋值,因为属性是有默认值的,不赋值系统认为操作无意义。
修饰类:不可继承
修饰方法:不可重写
全局常量:public static final,由一个或多个单词组成,单词之间用下划线隔开,所有字母前部大写。
eg: MAX_NUMBER
六、抽象类常见的问题
(1)抽象类不能实例化
(2)抽象类不能用final声明
(3)抽象类有构造方法,不能被用户创建,但是能被Java虚拟机创建
(4)必须使用public或protected修饰,因为priavte无法被继承,默认缺省为public
七、接口
(1)一个类可以实现多个接口
(2)接口之间可以多继承、
(3)接口的属性默认为public static final
(4)接口的方法默认为public abstract
八、多态
父类的引用指向子类的对象
九、代码块
(1)普通代码块
(2)构造代码块
随着每次对象的创建执行一次,且执行在构造方法之前。构造方法不一定会执行,但是构造代码块一定会执行。
(3) 静态代码块,其实就是在构造代码块的前面加上static
随着类的加载而执行,只执行一次
执行顺序:静态代码块>构造代码块>构造方法
十、内部类
(1)成员内部类
成员内部类可以无条件访问外部类的所有属性和方法,包括priavte和static
(2)局部内部类
(3)匿名内部类
属于局部内部类的一种
1.必须有父类或者接口,但二者不可兼得,同时也只能实现一个类或一个接口;
2.不能定义构造函数
3.不能存在任何静态成员变量和成员方法
4.不能是抽象的
5.所有的局部内部类只能访问final型的局部变量
(4)静态内部类
就是成员内部类加上static,唯一的不同就是使用内部类前可以不用创建外部内的实例,直接使用类名即可
十一、异常处理
1.异常体系结构
分为受检异常和非受检异常(运行时异常,即RuntimeException)。一旦异常产生,JVM会产生对应的异常类的实例化对象
2.try-catch-finally
(1)无论是否发生异常,finally必然执行。思考一下下面这种情况finally会执行吗,答案是肯定的。虽然try中有return,代码运行到return的时候系统会进入准备结束的阶段,在这个阶段finally会执行。
(2)思考下面的代码结果是多少,答案为28
思考下面的代码,答案是10
看完上面2种代码,你的内心一定是,what fuck??? why??? Are you kidding me???
稍安勿燥,这是面试的时候很多人极易死在的地方,其实也很好理解。其实很好理解return a和return p中的a和p不是直接return原来的a和p,而是复制,那你可能又会问,那为什么都是复制结果却是相反的呢。因为a是非引用数据类型,而p是引用数据类型,前面已经用栈和堆分析过了,说到这里就应该好理解了。
(3)需要注意的是exit是退出虚拟机,此时finally不会执行
3.throws
4.throw
用的比较少,哪有人喜欢给自己挖坑的,直接if判断不香吗