Java基础——知识总结

字节码文件:

  • JVM可以理解的代码就叫做字节码 .class文件

类加载的入口:

  • 是 .class文件

JDK和JRE区别:

  • JRE是Java的运行环境,包括JVM和核心类库
  • JDK是Java的开发工具包,比JRE多了javac编译器和工具(如jdbc)

Java和C++的异同:

  • 都是面向对象语言,但是Java不提供指针访问内存、Java类是单继承而C++是多继承、Java有自动内存管理机制

Java为编译型同时又为解释型语言:

  • 先通过javac编译生成 .class字节码文件,然后交给JVM解释运行
  • Java源代码 → 编译器 → .class字节码文件 → JVM → JVM解释器 → 二进制机器码 → 程序运行

字符型常量和字符串常量的区别:

  • 字符型常量:单引号,相当于一个整形值(ASCII),占用2个字节
  • 字符串常量:双引号,代表一个地址值,占用若干字节

变量大小

标识符和关键字:

  • 标识符就是指变量或者类名,关键字就是public/if/while之类的

continue:

  • 跳出当前一次的循环,直接进入下一次循环

break:

  • 跳出整个循环体,直接执行循环体下面的语句

return:

  • 跳出所在方法

Java泛型:

  • Java的泛型是伪泛型,因为在编译期间泛型类型会被擦除掉,转换为具体的类型,这就是所谓的泛型擦除

==:

  • 基本类型中(“==”比较的是变量的值)
  • 引用类型中(“==”比较的是引用对象的地址值,如对象、数组)

equals():

  • “equals”是Object中的方法,所以说只有对象可以使用equals进行比较,Object中的equals方法比较的是对象的地址值,也就是“==”,但是不同的类可以重写equals方法进而比较类是否相等(如String类)

hashcode():

  • “hashcode”是Object中的方法,用于返回对象在「哈希表」中的索引位置,是一个16位长度的int整数,Object中的hashcode()是native本地方法,是通过C++将对象地址转换为int整数返回的

为什么要有hashcode:

  • 用HashSet集合进行举例,每一次添加元素都会比较元素是否为同一个元素,先比较hashcode,因为hashcode复杂度为O(1),计算很快,如果hashcode相同再调用equals()方法,这样可以大大减少equals()方法的调用次数,因为equals()计算比hashcode慢很多

为什么重写equals()方法后要重写hashcode()方法:

  • 因为两个对象相等,hashcode也一定相等,但是hashcode相等,不一定对象就一定相等,如果没有重写hashcode()方法,对象不可能会相等

HashCode注意事项:

  • 如果两个对象相等,则hashcode一定也是相同的
  • 两个对象相等,对两个对象分别调用equals方法都返回true
  • 两个对象有相同的hashcode值,它们也不一定是相等的。因此,equals方法被覆盖过,则hashCode方法也必须被覆盖
  • hashCode()的默认行为是对堆上的对象产生独特值。如果没有重hashCode()则该class的两个对象无论如何都不会相等(即使这两个对象指向相同的数据)

基本类型

8大类型及其常量池:

  • 8大类型部分实现了常量池(Byte,Short,Integer,Long,Character,Boolean),Float/Double没有实现常量池,前4种的类型实现了[-128,127]的缓存数据池,Character创建数值[0,127]范围的缓存数据池,Boolean直接返回True/Flase,如果超出了缓存数据池则会创建新对象

Java值传递:

  • Java只有值传递
  • 对于基本类型来说,作为方法的参数,只是复制一个变量同时给这个变量赋予基本类型的值进行使用
  • 对于引用类型来说,作为方法的参数,将对象或数组的「地址」也就是「引用变量」复制一份,将这个值作为方法的参数,而不是直接将引用作为方法的参数。所以说看上去像是引用传递,但其实Java都是值传递

重载与重写:

  • 重载(发生在同一个类中):
    • 方法名必须相同
    • 方法参数的类型/数量/顺序必须有一个不同
    • 返回值类型和方法的修饰符可以不同
  • 重写(发生在父类和子类中):
    • 方法名必须相同
    • 方法参数必须相同
    • 返回值类型范围小于等于父类
    • 抛出的异常范围小于等于父类
    • 方法的修饰符范围大于等于父类
    • 如果父类方法访问修饰符为private/final/static,则子类不能重写该方法
    • 构造方法不可重写

深拷贝和浅拷贝:

  • 浅拷贝:是指对于基本类型为值传递,对于引用类型进行原引用地址的值传递
  • 深拷贝:是指对于基本类型为值传递,对于引用类型,创建一个新的对象,并复制其内容,再让引用类型指向其新创建的对象
  • Object类中的clone()为浅拷贝,如果想进行深拷贝,则需要对于clone的对象中的引用类型再调用一次clone(),或者进行序列化之后再反序列化回来

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FZxS4rla-1628995938837)(https://s3-us-west-2.amazonaws.com/secure.notion-static.com/cdf98fe4-297f-4498-9af1-73e5eabfdcbf/Untitled.png)]

类中定义一个无参构造且无作用的方法的意义:

  • 在子类执行构造方法之前,如果没有使用super()调用父类的特定构造方法,就会默认调用父类的无参构造方法,而父类如果只定义了有参构造方法,而没有无参构造方法且子类又没有在子类构造方法调用之前调用super()则会编译发生错误

成员变量和局部变量:

  • 成员变量:属于类的,是对象的一部分,随着对象的创建销毁而创建销毁,如果没有赋初值会赋予默认的值
  • 局部变量:属于方法或是方法中定义的参数,是方法的一部分,随着方法的调用而自动消失(JVM虚拟机栈中的入栈和出栈),不会自动赋予默认值

封装、继承、多态:

  • 封装:封装是指对于一个类会将必要的信息封装进类内部,使得外部不能直接访问,但是可以提供一些方法进行间接访问
  • 继承:继承是指不同类之间会存在相同的地方,可以让子类继承父类的一些特点,提高代码的重用(子类拥有父类的所有的非private的属性和方法,但是父类私有的属性或方法是无法访问的,只是拥有)
  • 多态:多态是指一个对象具体多种状态,具体指「父类引用指向子类实例」(左编译右运行,引用类型调用的方法是哪个类的方法,在运行时才能确定、多态不能调用只在子类中有而父类没有的方法、如果子类重写了父类的方法,调用的是子类方法,反之为父类方法)
    • 实现多态的2种方法:
      • 继承
      • 接口

接口与抽象类:

  • 抽象类可以存在普通成员函数,而接口只能存在public abstact方法
  • 抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是public static final类型
  • 抽象类只能继承一个,而接口可以实现多个
  • 抽象类是一般类的部分抽象,而接口是一般类的完全抽象
  • 抽象类和接口都不能实例化
  • 抽象类是对类的抽象,是一种模版设计;而接口是对行为的抽象,是一种行为的规范

Object常用8个方法:

  • getClass():获取当前对象的类型
  • toString():输出对象的成员变量,通常重写
  • hashcode():获取对象的hashcode值
  • clone():浅拷贝当前对象
  • wait():将当前线程等待该对象的锁,wait()一直等待,直到获取锁为止,也可以wait(Long)设定timeout
  • notify():唤醒在该对象上等待的某个线程
  • notifyall():唤醒在该对象等上等待的所有线程
  • finalize():用于释放资源,进行GC,不能直接调用,JVM底层自动调用

NIO:

  • 传统IO:是一个字节地处理数据,只能是阻塞的
  • NIO:是以块(Buffer缓冲区)的形式处理数据,可以实现非阻塞
  • IO的实际场景:文件IO、网络IO
  • NIO的核心组成部分
    • Selector(选择器):检查多个Channel的状态变更情况,将请求交给某个空闲的线程处理
    • Channel(管道):运输数据的载体
    • Buffer(缓冲区):存储数据的地方

String、StringBuffer、StringBuilder区别:

  • String:final关键字修饰,不可变,每次对String类型的值进行改变的时候,都会产生新的String对象,然后将引用指向新的String对象。而StringBuffer每次都会对StringBuffer对象本身进行操作,而不是生成新的对象并改变对象的引用。String有字符串常量池
  • StringBuffer和StringBuilder(可变长字符串)都是在原对象操作的
  • StringBuffer是线程安全的,StringBuilder是线程不安全的
  • StringBuffer内的方法都是synchronized修饰的
  • 性能:
    • StringBuilder > StringBuffer > String

自动装箱和拆箱:

  • 装箱:将基本类型用它们对应的引用类型包装起来
  • 拆箱:将包装类型转换为基本数据类型

在一个静态方法内调用一个非静态成员为什么是非法的:

  • 静态方法可以不通过对象进行调用,因此在静态方法里,不能调用其他非静态变量,也不可以访问非静态变量成员

final关键字:

  • final修饰变量:
    • 修饰「基本数据类型」的变量,则其数值一旦在初始化之后便不能更改
    • 修饰「引用类型」的变量,则在对其初始化之后便不能再让其指向另一个对象,但是引用指向的对象是可以变的
    • 修饰「类变量」,只能在static{}静态代码块中指定初始值,或者在声明类变量时指定初始值
    • 修饰「局部变量」,可以在非静态代码块、声明该变量、构造器中指定初始值
  • final修饰类:
    • 类不能被继承
    • final类种的所有成员方法都会被隐式地指定为final方法
  • final修饰方法:
    • 子类无法重写父类的final方法
    • 类中所有的private方法都隐式地指定为final

Java异常处理:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NAzlwtp9-1628995938840)(https://s3-us-west-2.amazonaws.com/secure.notion-static.com/da10a20c-4b81-43f7-848f-72f8600894fd/Untitled.png)]

  • Java中所有的异常都有一个共同的父类 java.lang包下的Throwable类
  • Throable类有2个重要的子类:Exception(异常)、Error(错误)
  • Exception能被程序本身处理(try-catch),不会导致程序停止
    • RunTimeException(运行时异常)
    • CheckedException(检查异常)
  • Error是无法处理的错误,一旦出现,程序被迫停止运行(只能尽量避免)

transient关键字:

  • 阻止实例中那些用此关键字修饰的变量序列化
  • 当对象被反序列化时,被transient修饰的变量值不会被持久化和回复
  • transient只能修饰变量,不能修饰类和方法

Java IO流:

  • InputStream/OutputStream:字节输入输出流的父类
  • Reader/Writer:字符输入输出流的父类

BIO、NIO、AIO区别:

  • BIO(Blocking IO):同步阻塞IO,数据的读写必须阻塞在一个线程内等待其完成
  • NIO(Non-Blocking IO):同步非阻塞IO,提供Channel,Selector,Buffer等抽象
  • AIO(Asynchronous IO):异步非阻塞IO,异步IO是基于事件和回调机制实现的,也就是应用操作之后会直接返回,不会阻塞在那里,当后台处理完成,OS会通知相应的线程进行后续的操作

String s = new String("abc")创建了几个实例:

  • 栈中 s 引用
  • 堆中新String对象
  • 指向常量池中的 “abc”

String对象的intern()方法:

  • String对象的intern()方法首先会检查「字符串常量池」是否存在“abc”,如果存在则返回该「字符串的引用」,如果不存在,则把“abc”添加到字符串常量池,并返回该「字符串的引用」
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值