java - 基础知识
java - 基础知识
内存结构
- 栈 存放局部变量
堆 存放对象,数组
- 变量 成员变量 vs 局部变量(方法内,方法形参,构造器,构造器形参,代码块内)
四种访问权限修饰符
修饰符 | 类内部 | 同一个包 | 不同包的子类 | 同一个工程 |
---|---|---|---|---|
private | yes | |||
default | yes | yes | ||
protected | yes | yes | yes | |
public | yes | yes | yes | yes |
对于class的修饰符只有public 和default
JavaBean 符合以下标准的类
- 类是公共的
- 有一个无参的公共构造器
- 有属性,且有对应的get,set方法
用户可以使用JavaBean 将功能,处理,值,数据库访问和其他任何可以用java代码创造的对象进行打包,并且其他的开发者可以通过内部的JSP页面,Servlet,其他JavaBean,applet程序或者应用来使用这些对象。用户可以认为JavaBean 提供了一种随时随地的复制和赞贴的功能,而不用关心任何改变。
this
- this可以调用属性,方法,构造器
- this() 调用构造器,可以显示的使用this(形参列表)方式,调用指定的其他构造器,不能形成递归
继承
- 子类继承后,具有父类的所有属性和方法 ,private属性和方法仍然认为获取到了,但是因为封装的原因,不能直接调用
- 所有的java类处 java.lang.Object 外,都直接或者间接继承了java.lang.Object类
- 当子类和父类中定义同名属性时,我们想要在子类调用父类中的属性方式,必须使用“super.属性”,子类不会覆盖父类的属性
- 我们可以在子类构造器中显示的使用super(形参列表),调用父类的构造器,必须声明在子类构造器的首行
- 在构造器的首行没有显示的声明this(形参列表)或super(形参列表),则默认调用的是父类的空参的构造函数
子类对象的实例化过程
- 从结果来看 子类继承父类以后,就获取了父类所有的属性和方法
- 创建子类的对象后,在堆空间中,就会加载所有父类中声明的属性
- 从过程看 当我们通过子类的构造器创建子类对象时,我们一定会直接或者间接的调用父类的构造器,直到调用了java.lang.Object类中空参的构造器为止。正因为加载过所有父类的结构,所有内存中才会有所有父类的结构,并且使用。
- 虽然创建子类对象时,调用了父类的构造器,但是只创建了一个对象,就是new 出来的对象
多态性
- 对象的多态性,父类的引用指向子类的对象
多态的使用
- 当调用子父类同名同参方法时,执行的是子类重写父类的方法
- 编译期,只能调用父类中声明的方法 ,但是运行期,我们实际执行的是子类重写的方法 只适用方法,编译看左边,运行看右边
- 对象的多态性,只使用于方法,不适用于属性。 编译和运行都看左边。
- 虚拟方法调用 子类中定义了与父类同名同参数的方法,在多态情况下,将此时父类的方法称为虚拟方法,父类根据赋给它不同子类对象,动态调用属于子类的的该方法,这样的方法调用在编译器是无法确定的。
- 编译时类型和运行时类型。方法调用是在运行时确定的,动态绑定。
- 多态是个运行时行为
- 若子类重写了父类的方法,就意味着子类里定义的方法彻底覆盖了父类里的同名方法,系统将不可能把父类的的方法转移到子类中。(编译看左边,运行看右边)
- 对于实例变量则不存在这样的现象,即使子类里定义了与父类完全相同的实例变量,这个实例变量依然不可能覆盖父类中定义的实例变量(编译运行都看左边)
## 方法的重写
- 方法名,形参列表相同
- 权限修饰符不能小于父类,不能重写private权限的方法
- 返回值不能大于父类的返回类型,
- static 方法不涉及到重写
静态变量
- 静态变量随着类的加载而加载
- 静态变量加载要早于对象的创建
- 类只会加载一次, 静态变量也只会存在一份
静态方法
- 只能调用静态变量或者其他静态方法,因为是随着类的加载而加载,其他实例变量还没有,所以this,super是不能用的。
栈,堆,方法区
- 栈,静态变量
- 堆:new 出来的结构 对象,数组
- 方法区: 类的加载信息,静态域,常量池
抽象与接口
抽象
- 抽象类,不可以实例化,一定有构造器,便于子类实例化时调用,通常在开发中,都会提供抽象类的子类,让子类对象实例化。
- 抽象方法,没有方法体,只有声明。 抽象方法一定是在抽象类。
- 若子类重写了父类的所有 抽象方法后,则此子类可以实例化,若子类没有重写父类的所有的抽象方法,则此子类也是一个抽象类,需要使用abstract修饰。
接口
- interface和类是并列的结构,通过implements
- 如何定义接口:JDK7及以前 只能定义全局常量和抽象方法(public static final(书写时可以省略),public abstarct)
- JDK8 新增了 静态方法和默认方法。
- 接口中是不可以定义构造器的,意味着接口不可以实例化
- 如果实现类覆盖了接口中所有的抽象方法,则此实现类可以实例化,如果没有则实现类认为接口
- java类可以实现多个接口,弥补了java单继承性
- 接口与接口之间可以继承,并且可以多继承 ### jdk8 新特性
- 静态方法和默认方法
- 接口中定义的静态方法,只能通过接口调用
- 通过实现类的对象,可以调用接口中的默认方法
- 如果子类继承的父类和实现的接口中声明了同名同参数的默认方法,那么子类在没有重写此方法的情况下,默认调用的是父类中同名同参数默认(default)方法
- 接口冲突: 如果实现类实现了多个接口,而这多个接口中定了同名同参数的默认方法,那么实现类没有重写此方法的情况下报错
- 调用接口中的默认方法 Interface.super.method()
## 抽象类和接口的共同点以及区别
- 相同点: 不能实例化,都可以被继承
- 不同 抽象类:有构造器, 接口:不能声明构造器 ,类单继承,接口可以多继承
异常处理
### ERROR 一般不编写针对性的代码进行处理 java虚拟机无法解决的严重问题,如JVM系统内部错误,资源耗尽等严重情况,例如栈溢出:StackOverflowError,堆溢出:OutOfMemoryError,
### Exception
- 其他编程错误或偶然的外在因素导致的,可以使用针对性的代码进行处理
- 例如空指针,数组越界,除数为0
- 一般两种解决方法,遇到错误终止程序的运行。另一种方法时由程序编写程序时,考虑到错误的检测,错误消息的提示,以及处理。
- finally 是可选的,finally 中声明的是一定会被执行的代码,即使catch中又出了异常,try中有return语句,catch中有return 语句等, 也会先执行finally的语句。
- 像数据库连接,输入输出流,网络编程Socket 等资源,JVM是不能自动回收的,我们需要自己手动的进行资源的释放。此时的资源释放,就需要声明在finally中 ### 体会
- 使用try-catch-finally 处理编译时异常,是将编译时可能出现的异常,延迟到运行时出现
- 开发中,由于运行时异常比较常见,所以我们通常就不针对运行时编译try-catch-finally
本文由作者按照 CC BY 4.0 进行授权