JAVASE笔记

重要机制:就近原则机制
面向对象机制三大机制:封装、继承、多态
继承的作用:
  • 代码复用

  • 核心作用,是实现方法覆盖与多态机制的基础条件

注意:java类与类之间的继承只能是单继承,没有多继承机制,但允许间接继承(我认为是变相的多继承)

方法覆盖的应用场景:子类继承父类中的方法已经无法满足该类的业务需求时刻
代码片段上方法重写的条件
  • 必须有继承关系下重写父类方法

  • 重写方法具有相同的返回值、参数列表

  • 访问权限不能更低

  • 抛出的异常不能更多

Object的toString方法覆盖

方法重载与方法覆盖的区别:

  • 方法重载是在同一个类中,方法覆盖是在继承关系的子类中

  • 方法重载是指方法名相同,参数列表不同;方法覆盖是重写方法具有相同的返回值、参数列表且访问权限不能更低、抛出的异常不能更多

多态
多态 机制原理前提
  • 向上转型和向下转型(引用类型) 自动类型转换和强制类型转换(基本数据类型)

  • 向上转型:子类型——>父类型 向下转型:父类型——>子类型

什么是多态?
  • 父类型引用指向子类型对象

  • 多态是指在编译阶段与运行阶段有两种状态,例如

  • public class Animal{ public void move(){ System.out.println("动物在移动") }}class Cat extends Animal{ @override public void move(){ System.out.println("猫在走猫步") }}Animal cat = new Cat()cat.move()

  • 由于cat对象的引用类型是Animal类型的,在编译阶段编译器会先寻找类加载时存储的move实例方法并绑定该方法给cat引用,可以说是静态绑定。

  • 在运行阶段发现cat引用类型实际是Cat构造方法所创建的对象 ,则去堆内存中寻找cat对象中的实例方法move,发现是方法覆盖则动态绑定

  • 总的来说

  • 编译阶段绑定父类型方法

  • 运行阶段绑定子类型对象方法

什么时候需要进行向下转型?
  • 当父类型引用调用的方法是子类型对象特有的才进行向下转型

  • 向下转型有风险:可能会报ClassCastException(类型转换异常)

  • 需要通过instanceof在运行阶段动态判断该引用指定的对象是否是某种类型

this与super对比

创建一个对象,堆区中该对象的实际存储

该子类型对象继承父类型部分特征时,创建子类对象并不会创建父类型对象,始终是创建了一个对象,尽管调用了super(),该方法的作用只是初始化其父类型特征

this是引用,存储着该对象的内存地址 super只是代表其父类型特征,并不是引用

final:最终的、不可变的
  • final修饰的类不可被继承

  • final修饰的方法不可覆盖

  • final修饰的变量不可变,而修饰的引用类型所指向的对象不可变(引用地址),对象里的内容可变

  • final修饰的成员变量必须手动赋值,否则编译报错;final修饰的局部变量不会默认赋值,但也不能二次赋值

引入常量

既然成员变量已用final修饰,说明不可变,但依旧是成员变量,创建多少个对象就在堆内存为该成员变量分配内存空间,造成浪费

需将其变为类级别的,即static final 修饰是指常量,在类加载就分配好内存空间且值不可变

例如String类型:jdk默认使用的是Public Static Final 修饰,就算重新赋值也只是重新赋值其引用,之前的字符串依旧在内存空间存在

抽象类与接口
什么是抽象类?
  • 抽象类是对类与类之间进行提取共性

  • 抽象类不可创建对象

  • 抽象类与抽象类之间还能抽象

  • 抽象类不是完全抽象的,因此抽象方法可有可无

什么是接口?
  • 接口也是一种引用数据类型

  • 接口一般是”行为”上的抽象,

  • 什么是行为上的抽象?金典案例:比如说所有厨师都会做一道番茄炒蛋,但不同的厨师做出来的口味是不一样的

  • 接口只能有常量和抽象方法,接口是完全抽象的

  • 非抽象类实现接口必须重写所有抽象方法

  • 接口与接口之间可继承

  • 使用未继承的多个接口也可通过编译时的向下转型,只是运行阶段会报ClassCastException错误

  • 接口之间可进行多继承(维护类与类之间的单继承机制的缺陷)

接口在开发中的作用
  • 核心:提高程序的扩展性,降低耦合度,实现OCP原则(对修改关闭,对扩展开放)

  • 降低的是谁与谁的耦合度?是接口的调用者与接口的实现者

  • 使用接口离不开多态机制

为什么会有这样的功效呢?

因为开发的面向抽象编程即是面向接口编程。接口可以认为是一个完全抽象的工具类,我可以有多种实现,只需在某个类中定义该接口成为该类的属性,则说明我有一个抽象的工具,通过多态,我可以使用多种具体的工具。面向这个工具的调用者来说,我不需要工具的实现原理是什么,只知道有没有这种工具。面向实现者来说,我只需要完成工具的一种实现或多种实现,不需要知道调用者使用了哪种工具。

抽象类与接口的区别:
  • 抽象类有构造方法,但这个构造方法是给非抽象子类创建对象时初始化父类的;接口没有构造方法,因为接口是完全抽象的,接口里只有常量和抽象方法,不需要初始化。想要初始化,只能子类实现接口去初始化

包装类

为什么会出想包装类?

因为基本数据类型已经不足以对开发的日后实现,以及方法中的参数基本是引用数据类型,没有包装类是无法进行传参的。

包装类的机制:自动装箱与自动拆箱

异常处理
异常

在Java应用程序中,异常处理机制为:抛出异常、捕获异常 当一个方法出现错误引发异常时,方法创建异常对象并交付运行时系统进行处理。 异常对象通常包含异常类型和异常出现时的程序状态等信息。 运行时系统负责寻找处置异常的代码并执行。 在方法抛出异常之后,运行时系统将转为寻找合适的异常处理器。

异常在java中是以类与对象的形式存在

异常的两种分支
  1. 编译时异常(Exception直接继承类)(也叫受检异常)

编译时异常不是在编译阶段发生的异常,而是在编写代码需要进行预处理的异常,所有异常都是发生在运行阶段

因为异常是通过new异常类产生的

发生概论较高的异常:编译时异常 为什么?因为由于程序员和比编译器的检测,会对该类异常进行预处理,否则会报错

  1. 运行时异常(RuntimeException)(未受检异常)

java对异常处理的两种方式
  1. 在声明方法处使用throws关键字,将异常抛给上一级(谁调用该方法就抛给谁)

  1. 使用try~catch捕捉异常,该方法是真正的解决该异常

当异常被抛到main依旧使用throws抛出异常时,异常被抛到了jvm虚拟机则会程序终止

异常处理细节
  • 我们程序中的异常来自哪里?

  • 一般来说是来自sun公司写好的API中,比如说创建输入流对象时,其构造方法中使用了throws关键字抛出,并且在构造方法里有throw(new 异常的构造方法)。由于调用了输入流的构造方法,因此异常对象被抛到此处。

  • try~catch深入

try{ m1();//若该方法出现异常,在try代码块后面的程序不会执行,会被catch捕捉异常 m2();}catch(exception e){ //e引用是存储的是new出来的异常对象的内存地址,也可使用多态机制,但一般最好精确处理异常,方便代码调试}catch(ClassNotFindException e){//也可多次catch,但catch捕捉的异常引用必须由小到大。因为父类型异常包含了子类型异常可直接在 该catch进行处理}

  • 那以后的开发该如何选择异常处理方式呢?

  • 如果需要调用者知道该异常使用throws,其余都使用try~catch自行处理

  • 异常对象常用方法

  • e.getMessaeg()

  • e.printStackTrace() 该方法会打印异常追踪信息,有利于debug,使用最多的,五颗星

  • finally与try联合使用

  • finally一般用于执行资源的释放或关闭

  • 自定义异常

集合
Collection接口
Map
HashMap的put(key,value)和get(key)的实现原理

HaspMap的key部分实际存放到HashSet集合,因此HashSet的equal和hashCode方法需要按照自己的规则重写。

序列化与反序列化
什么是序列化?

将内存的对象持久化到磁盘中,一般是实体类实现Serialziable,当没有序列版本号java虚拟机则自动默认生成。(默认自动生成序列化版本号缺陷:无法序列化后修改代码重新编译)

多线程
什么是多线程?
  • 多线程是指在一个进程中开多个线程并发执行,各不影响,各自执行。线程与线程之间共享堆区与方法区的内存,独享栈内存。可以将一个线程看做是一个栈,一个线程是进程的执行单元

创建多线程
  • 线程对象.start()方法瞬间执行 则会开启一个分支线程,jvm会开辟一个新的栈空间

  • 在主方法调用run方法并不会

方法一:直接继承Thread,创建对象
方法二:实现Runable接口,将可运行对象传入new Thread()

线程的生命周期
获取当前线程对象
  • Thread.currentThread()

线程休眠
  • Thread.sleep() 让当前线程进入休眠状态(放弃当前时间片)

线程休眠的终止
  • 线程对象.interrupt()

  • 线程休眠的终止依靠异常机制,上述方法会导致sleep方法的异常

线程安全问题
什么时候会出现线程安全?
  • 当出现多线程并发

  • 共享数据

  • 共享的数据发生修改

如何解决线程安全?
  • 使用同步机制synchronized(数据共享的对象){}

  • 实现原理

反射机制
与反射机制的相关类

获取字节码的三种方式
  • Class.forname("完整的类名(包括包名)")

  • 调用该方法会导致类加载,使得静态代码块执行 重点:若希望只执行静态代码块的代码可通过该方法

  • 引用.getClass()

  • 所有数据类型都有class属性(包括基本数据类型)

获取绝对路径,使得程序的移植性更高

String Path = Thread.currentThread().getContextClassLoader().getResource("类目录路径(必须是在src目录下否则报空指针异常错误)")

  • 直接以流的形式返回

  • InputStream in = Thread.currentThread().getContextClassLoader().getResourceAsStream("类目录路径(必须是在src目录下否则报空指针异常错误)")

获取properties资源可通过资源绑定器

使用反射机制调用方法
  1. 获取字节码文件Class

  1. 创建对象 ——>获取构造方法Constructor再创建

  1. 使用invoke方法调用(但方法重载时,需要通过实参列表区分方法,实参列表也是Class类型,因此使用数据类型.class)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值