Java基础内容
2024-09-25 10:11:20 18 举报
AI智能生成
Java基础内容
作者其他创作
大纲/内容
面向对象
核心概念
对象
对象是类的实例化结果
它具有独立的内存空间,可以调用类中定义的方法和访问类中定义的属性。
类
面向对象的基本单位
它可以看作是对象的模板,描述了对象的属性和行为
封装
是将数据和方法包装在类中,对外部隐藏实现细节,只提供公共的访问接口。
通过封装,可以实现数据的安全性和代码的复用性,提高程序的可靠性和可维护性。
继承
是一种机制
它允许创建一个新的类,从已有的类中继承属性和方法。
子类继承了父类的特性,可以重写父类的方法或增加新的方法,实现代码的复用和扩展。
多态
是指同一类型的对象,在不同的情境下可以有不同的表现形式。
通过多态,可以提高代码的灵活性和可扩展性,使得程序更易于维护和拓展。
数据类型
java8种基本数据类型
boolean ~
为什么boolean没有规定字节数?
byte 1个字节
char 2个字节
shot 2个字节
int 4个字节
long 8个字节
fload 4个字节
double 8个字节
8种包装类型
分类
Boolean
Byte
Character
Short
Integer
Long
Double
缓冲池
什么是缓冲池?
那些包装类具有缓冲池?
Byte
Short
Character
Integer
Long
String相关
String
改变
在java8中String使用char数组存储数据
在java9中String使用byte数组存储字符串,并且同时使用coder来标识使用了哪种编码
String为什么被声明为final(声明为final的好处?)
什么是StringPool(StringTable)
相关资料
- StringPool是Java中的一个字符串常量池,用于存储字符串对象的引用。它是在堆内存中的一个特殊区域,用于提高字符串的重复利用率和节省内存空间。
- StringPool中的字符串对象是不可变的,一旦创建就不能被修改。这是因为字符串的不可变性可以提高字符串的安全性和线程安全性。
- StringPool的实现方式有两种:基于永久代的实现方式和基于堆的实现方式。在Java8之后,永久代被元空间取代,StringPool被移至堆中。
- StringPool中的字符串对象是通过字符串字面量创建的,也可以通过调用String类的intern()方法将字符串对象添加到StringPool中。
- StringPool的主要作用是提高字符串的重复利用率。当程序中多次使用相同的字符串字面量时,它们都将指向StringPool中的同一个字符串对象,从而节省了内存空间。
- StringPool的另一个作用是加速字符串的比较。由于StringPool中的字符串对象是唯一的,可以通过比较字符串对象的引用来判断两个字符串是否相等,从而提高了比较的效率。
- StringPool的大小是有限的,它的最大容量取决于具体的Java虚拟机实现。当StringPool中的字符串对象达到一定数量时,新的字符串对象将不再被添加到StringPool中,而是在堆中创建新的字符串对象。
StringBuilder
线程不安全,可以被改变
StringBuffer
线程安全,内部被synchronized同步
关键字
final
可以声明的位置
类
该类不能被继承
方法
该方法不能被重写
数据
基本类型
使数值不能够被修改
引用类型
引用不能变,但是被引用变量的对象本身可以被修改
final修饰的变量也可以被修改
使用java提供的反射技术,并且关闭安全校验也可以修改其值
static
可以声明的位置
类
方法
成员变量
静态代码块
初始化顺序
1.父类(静态变量,静态代码块)
2.子类(静态变量,静态代码块)
3.父类(实例变量,普通代码块)
4.父类构造方法
5.子类(实例变量,普通代码块)
6.子类构造方法
继承
访问权限
private 类访问
default 包访问
protected 继承访问
这个修饰符在继承体系中成员对于子类可见,但是这个修饰符对于类没有意义
public
重写
子类只能够重写父类非私有的的,非静态的方法
子类重写父类的方法可以扩大访问权限
子类方法抛出的异常类型必须是父类抛出异常类型或为其子类型。
抽象类和接口
接口
新特性
在java8中接口可以有default方法,也可以有静态方法
但是静态方法不能够被重写,default方法可以被重写
接口中的方法默认都是public的,并且不允许定义为其他的
接口中的字段都是static和final的
抽象类
抽象类和抽象方法都使用 abstract 关键字进行声明。如果一个类中包含抽象方法,那么这个类必须声明为抽象类。
抽象类不能被实例化,只能被继承。
内部类
概述
内部类是定义在另一个类内部的类,可以访问外部类的成员变量和方法。内部类可以分为成员内部类、局部内部类、匿名内部类和静态内部类。
成员内部类
定义
在外部类的成员位置上定义的类。
可以使用public、protected、default和private修饰符。
可以访问外部类的所有成员,包括私有成员。
可以使用static修饰符,创建静态成员内部类。
可以使用final修饰符,创建常量成员内部类。
可以使用abstract修饰符,创建抽象成员内部类。
可以使用接口,实现内部类的多重继承。
访问方式
外部类名.内部类名 对象名 = 外部类对象.内部类对象;
局部内部类
定义
定义在方法内部的类。
只能访问方法内的final局部变量。
不能使用访问修饰符和static修饰符。
可以访问外部类的所有成员。
匿名内部类
定义
没有类名的内部类。
用于创建只需使用一次的类。
可以继承一个类或实现一个接口。
可以访问外部类的成员变量和方法。
静态内部类
定义
使用static修饰的内部类。
可以访问外部类的静态成员,不能访问非静态成员。
可以使用外部类的类名直接访问静态内部类。
总结
内部类是定义在另一个类内部的类,可以访问外部类的成员变量和方法。内部类可以分为成员内部类、局部内部类、匿名内部类和静态内部类。每种类型的内部类都有其特点和适用场景,开发者可以根据具体需求选择合适的内部类类型。
异常处理
分类
Exception
RuntimeException
非运行时异常
运行时异常和非运行时异常区别?
Error
OutOfMemoryError
StackOverflowError
ThreadDeath
...
Exception和Error的区别?
泛型
分类
泛型类
如果一个类继承了一个泛型类,要么在子类的泛型声明上上声明父类泛型参数,要么指定父类泛型的具体类型。
泛型方法
泛型接口
泛型抽象类
泛型的通配符和泛型的上限和下限
在使用”?“只能接收,不能修改。
上边界通配符会导致修改失效,但是获取有效
下边界通配符会导致获取有效,但是修改失效
原因
集合容器
Collation
List
ArrarList
动态数组实现
初始容量10(只有在第一次添加的时候才会真正分配初始容量),每次扩容1.5倍,如果扩容1.5倍还不够就会使用最小容量
线程不安全
实现了RandomAccess接口,支持快速随机访问
LinkedList
双向链表
线程不安全
插入和删除时间复杂度几乎为O(1)
不支持快速随机访问
空间消耗比ArrayList消耗更大(因为每个节点都比ArrayList多了两个引用)
Vector
动态数组实现
线程安全
初始容量10,每次扩容2倍,并且可以指定每次容量的增量
可以理解为加了synchronized的ArrayList
CopyOnWriteArrayList
原理
写入时复制
特点
适合大量读操作,但是不适合大量的写操作
可以读写分离,但并不是读写锁实现的
线程安全
初始容量0,每次写入的时候容量扩容,新的容量=插入容量+旧容量
Set
TreeSet
TreeMap换皮
HashSet
HashMap换皮
LinkedHashSet
LinkedHashMap换皮
CopyOnWriteSet
和CopyOnWriteArrayList原理一样
Queue
Deque
常用子类
ArrayDeque
BlockingQueue
常用子类
LinkedBlockingQueue
ArrayBlockingQueue
四组常用API
抛出异常
add
remove
element
有返回值,不会抛出异常
offer
poll
peek
阻塞等待
put
take
超时等待
offer(,,)
poll(,)
使用阻塞队列实现生产者和消费者模型
AbstractQueue
Map
HashMap
升级
在JDK1.7中HashMap使用数组加链表来实现
在JDK1.8中HashMap使用数组+链表+红黑树实现
JDK1.8原理
初始容量16(第一次插入才会真正分配)
每次扩容2倍
如果当前桶的容量大于装填因子*总容量就触发扩容
如果一个链表的节点个数超过8个,并且桶的长度超过64个则链表升级为红黑树,如果没有超过64个则单纯扩容2倍
首先先把hash值高16位和低16位按位与计算,然后计算桶位置算法是 index = (n - 1) & hash相当于index=hash%n
如果一颗红黑树的节点小于6个则红黑树退化为链表
线程不安全
可以存NULL
HashTable
线程安全
默认初始容量11,装填因子0.75
每次扩容容量是2倍+1
直接使用hasoCode的值作为hash值
TreeMap
红黑树实现
key自动排序
LinkedHashMap
链表实现
应用场景
HashMap是无序的,当我们希望有顺序地去存储key-value时,就需要使用LinkedHashMap
线程不安全
ConcurrentHashMap
JDK1.7
实现
分段锁 segment,锁的粒度更加精细
分段的数组+链表的形式
分段的数组+链表的形式
原理
get
get不需要加锁,采取volatile修饰共享变量
这样每次get的时候都可以获取最新的结构更新
由于遍历不需要加锁的原因是因为next是final。要么
是不为空返回,为空的话就加锁重读
这样每次get的时候都可以获取最新的结构更新
由于遍历不需要加锁的原因是因为next是final。要么
是不为空返回,为空的话就加锁重读
put
1.二阶段hash,第一阶段是定位到哪个segment
第二阶段是定位到哪个entry
第二阶段是定位到哪个entry
2.entry中,除了value,还有key,hash和next都是final修饰
意味着不能从中心或者尾部添加或者删除节点,一律添加到头部
意味着不能从中心或者尾部添加或者删除节点,一律添加到头部
3.通过count来统计段内的数据个数,只有新增和删除
会修改这个值,每次都是在上述俩个步骤的最后一步进行修改
会修改这个值,每次都是在上述俩个步骤的最后一步进行修改
remove
由于是final,所以删除节点的时候会删除某个节点
然后那个节点之上都复制,然后最后一个节点指向
被删节点的下一个节点
然后那个节点之上都复制,然后最后一个节点指向
被删节点的下一个节点
resize
扩容只会对段扩容而非整个桶
跟HashMap不同的是,段是先判断
是否需要扩容再put,而hashmap是
先put再判断是否要扩容
跟HashMap不同的是,段是先判断
是否需要扩容再put,而hashmap是
先put再判断是否要扩容
size
先尝试不锁住segment的方式来统计segment的大小
如果统计过程中,容器的count发生变化则采取加锁的方式
如果统计过程中,容器的count发生变化则采取加锁的方式
JDK1.8
取消了分段锁,而是采取了cas和synchronized来保证并发安全,
synchronized只锁住当前链表或者红黑二叉树的首节点,只要hash
不冲突,就不会产生并发,效率很高
synchronized只锁住当前链表或者红黑二叉树的首节点,只要hash
不冲突,就不会产生并发,效率很高
可以认为是JDK1.8版本你的HashMap+CAS和synchronized实现的
0 条评论
下一页