《Java基础知识点》

常量池

String aa = "ab"; // 放在常量池中
String bb = "ab"; // 从常量池中查找
aa == bb; // true
// String.equals()被重写过,比较的是对象的值,如果equals方法未被重写,就等价于"==",比较的是引用
// 重写equals时,必须重写hashCode,因为如果hashcode值相同,就会调用equals()方法来检查hashcode相等的对象是否真的相同。
// 如果两者相同,就不会让其加入操作成功
// StringBuffer和StringBuilder都继承自接口AbstractStringBuilder

java中的常量池分为两种: 静态常量池和运行时常量池
静态常量池:字面量和符号引用量

  • 字面量 :java语言层面常量的概念,如文本字符串,声明为final的常量值等
  • 符号引用量:属于编译原理方面的概念,包括类和接口的全限定名、字段名称和描述符、方法名称和描述符

运行时常量池:JVM在完成类装载操作后,将class文件中的常量池载入到内存中,并保存在方法区中,我们常说的常量池,就是指方法区中的运行时常量池

JVM虚拟内存分布:

  • 程序计数器:JVM执行程序的流水线,存放一些跳转指令
  • 本地方法栈:JVM调用操作系统方法所使用的栈
  • 虚拟机栈:是JVM执行java代码所使用的栈
  • 方法区:存放一些常量、静态变量、类信息等,可以理解成class文件在内存中的存放位置
  • 虚拟机堆:JVM执行java代码所使用的堆,存放对象实例和数组
    在这里插入图片描述
    JDK1.7及之后版本的 JVM 已经将运行时常量池从方法区中移了出来,在 Java 堆(Heap)中开辟了一块区域存放运行时常量池。
    在这里插入图片描述
    线程共享的区域有:
  • 方法区
  • 直接内存(非运行时数据区的一部分)
    线程私有的区域有:
  • 程序计数器
  • 虚拟机栈
  • 本地方法栈

HashCode和equals的相关规定:

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

java序列化

序列化:将对象写入到IO流中
步骤:

  1. 创建一个ObjectOutputStream输出流;
  2. 调用ObjectOutputStream对象的writeObject输出可序列化对象。

反序列化:从IO流中恢复对象(不会调用构造方法,反序列的对象是由JVM自己生成的对象,不通过构造方法生成)
步骤:

  1. 创建一个ObjectInputStream输入流;
  2. 调用ObjectInputStream对象的readObject()得到序列化的对象。

意义:序列化机制允许将实现序列化的Java对象转换为字节序列,这些字节序列可以保存在磁盘上,或通过网络传输,以达到以后恢复成原来的对象。序列化机制使得对象可以脱离程序的运行而独立存在。
实现方式:如果需要将某个对象保存到磁盘上或者通过网络传输,那么这个类应该实现Serializable接口或者Externalizable接口之一。


集合

List(对付顺序的好帮手):List接口存储一组不唯一(可以有多个元素引用相同的对象),有序的对象
Set(注重独一无二的性质):不允许重复的集合,不会有多个元素引用相同的对象
Map(用Key来搜索的专家):使用键值对存储。Map会维护与Key有关联的值。两个Key可以引用相同的对象,但Key不能重复,典型的Key是String类型,但也可以是任何对象

Vector:类的所有方法是同步的。可以由两个线程安全地访问一个Vector对象、但是一个线程访问Vector的话代码要在同步操作上耗费大量的时间
ArrayList:不是同步的,所以在不需要保证线程安全时建议使用ArrayList,否则使用Vector

底层实现

  • ArrayList:Object数组
  • Vector:Object数组
  • LinkedList:双向链表(JDK1.6之前为循环链表,JDK1.7取消了循环)
  • HashSet(无序,唯一):基于HashMap实现的,底层采用HashMap来保存元素
  • LinkeHashSet:LinkedHashSet继承于HashSet,并且其内部是通过LinkedHashMap来实现的
  • TreeSet(有序,唯一):红黑树
  • HashMap:JDK1.8之前由数组+链表组成,数组是HashMap的主体,链表则是为了解决哈希冲突而存在的(“拉链法”解决冲突)。JDK1.8以后在解决哈希冲突时有了较大的变化,当链表长度大于阈值(默认为8),将链表转换为红黑树,以减少搜索时间
  • LinkedHashMap:继承自HashMap
  • Hashtable:数组+链表组成的
  • TreeMap:红黑树(自平衡的排序二叉树)

红黑树:
二分查找树的特点:

  1. 左子树的值小于或等于它的根节点的值
  2. 右子树的值大于或等于它的根节点的值
  3. 左、右子树也分别是二叉排序树

二分查找树存在的问题:当有多个连续插入的值都小于(或大于)根节点时,会出现下述情况
在这里插入图片描述

红黑树的特点:

  • 节点是黑色或红色
  • 根节点是黑色
  • 每个叶子节点都是黑色的空节点(NIL)
  • 每个红色节点的两个子节点都是黑色。(从每个叶子到根的所有路径上不能有两个连续的红色节点)
  • 从任一节点到其每个叶子的所有路径都包含相同数目的黑色节点。

native

  • 凡是带了native关键字的,说明java的作用范围达不到了,会去调用底层语言的库,例如Thread中的start0
  • 流程:代码运行到native那一行,会去调本地方法栈,然后通过本地方法栈找到本地方法接口(JNI),然后再找到本地方法库
  • JNI的作用:扩展Java的使用,融合不同的编程语言为Java所用

Tips:

  1. 如果有些字段(类成员变量)不想序列化时,可以使用关键字transient修饰,transient只能修饰变量,不能修饰类和方法
  2. java 中的 length 属性是针对数组说的,比如说你声明了一个数组,想知道这个数组的长度则用到了 length 这个属性.
  3. java 中的 length() 方法是针对字符串说的,如果想看这个字符串的长度则用到 length() 这个方法.
  4. java 中的 size() 方法是针对泛型集合说的,如果想看这个泛型有多少个元素,就调用此方法来查看
  5. HashSet的底层是基于HashMap实现的
  6. 死锁的四个必须条件:
  • 互斥条件:该资源任意一个时刻只由一个线程占用
  • 请求与保持条件:一个进程因请求资源而阻塞时,对方已获得的资源保持不放
  • 不剥夺条件:线程已获得的资源在未使用完之前不能被其他线程强行剥夺,只有自己使用完毕后才释放资源
  • 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系
  1. 为什么调用start()方法时会执行run()方法,而不能直接调用run()方法:调用start方法方可启动线程并使线程进入就绪状态(真正的多线程),而run方法只是thread的一个普通方法调用,还是在主线程里执行的
  2. excute()和submit()的区别:
  • excute()用于提交不需要返回值的任务,所以无法判断任务是否被线程池执行成功与否
  • submit()用于提交需要返回值的任务。线程池会返回一个Future类型的对象,通过这个Future对象可以判断任务是否执行成功
  1. 通过工厂类Excutors创建的三种线程池类型:(这三个方法实际上都是调用的ThreadPoolExecutor的构造方法)
  • FixedThreadPool:返回一个固定线程数量的线程池。线程池中的线程数量始终不变
  • SingleThreadExecutor:只有一个线程的线程池
  • CachedThreadPool:可根据实际情况调整线程数量的线程池
  • AQS的两种资源共享方式:Exclusive(独占)–>公平锁和非公平锁,Share(共享)–>多个线程可同时执行
  1. Java创建对象的过程:
  • 类加载检查

  • 分配内存
    在这里插入图片描述

  • 初始化零值

  • 设置对象头:初始化零值后,虚拟机要对对象进行必要的设置,例如这个对象是哪个类的实例,如何才能找到类的元数据信息、对象的哈希码、对象的GC分代年龄等信息。这些信息存放在对象头中

  • 执行init方法

  1. 类加载的过程在这里插入图片描述
    类加载器有:
  • BootstrapClassLoader(启动类加载器,最顶层的加载类,负责加载%JAVA_HOME%/lib目录下的jar包和类或者被-Xbootclasspath参数指定的路径中的所有类)
  • ExtensionClassLoader(扩展类加载器):主要负责加载目录%JAVA_HOME%/lib/ext目录下的jar包和类,或被java.ext.dirs系统变量指定的路径下的jar包
  • AppClassLoader(应用程序类加载器):面向我们用户的加载器,负责加载当前应用classpath下的所有jar包和类
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值