Java基础入门
Java数据类型
需要注意的是char大小为2字节
类型转化
基本数据类型表示范围排序
小范围可直接赋值给大范围,类型会自动转换
要注意char可以直接转int 例如’a’会转为对应的ASCII码
运算符
Java运算符的优先级
口诀可以帮助记忆:
单算移关与,异或逻条赋
变量
局部变量(Local Variables):
方法,构造方法或任何块中定义的变量,一旦执行完毕,局部变量就会被销毁。
作用域: 局部变量的作用域只限于定义它们的块内。
声明: 局部变量必须在使用前声明,并且不会被赋予默认值,所以在使用前必须显式初始化。
成员变量(Member Variables,也称为字段或属性):
作用域:成员变量的作用域是整个类。
默认值:如果成员变量没有显式初始化,Java 会为它们赋予默认值。以下是成员变量的默认值:
数值类型(byte、short、int、long、float、double):0
char 类型:‘\u0000’(空字符)
boolean 类型:false
引用类型(对象和数组):null
数组
数组的比较equals()
数组是一种引用数据类型,equals()继承自Object, 没重写比较的不是数组中的内容
比较两个数组中的内容使用的是Arrays.equals()
面向对象
封装、继承、多态
static
继承
子类能够继承和重写哪些访问控制修饰的方法?
public 和 protected能够继承和重写
默认、无修饰符的只用相同包下的子类能够继承和重写
多态
多态的表现形式
- 编译时多态
方法重载:
必须改变参数列表,即参数的类型和个数不同,或类型和个数相同但顺序不同(也算重载)
可以修改返回类型,但只修改返回类型不算重载。 - 运行时多态
- 方法重写
外壳不变,核心重写!
方法名和参数列表要完全相同,返回类型可以修改
访问权限只能扩大不能缩小
异常可以缩小(更加确定)不能更大(超出原异常范围) - 接口多态
一个类实现了某个接口,那么可以通过接口类型的引用来引用该类的对象。这样,一个接口引用可以指向实现了该接口的多个不同类的对象,从而实现了接口类型的多态性。
- 方法重写
重写与重载的区别
构造方法
一般使用public修饰
没有返回值类型 , 注意: void也没有
方法名和类名相同 **注意: ** 允许类用和构造方法同名的方法, 但注意要有返回参数
构造方法可以重载
错题
子类构造方法调用super()
执行子类构造方法首先会调用父类构造方法,默认调用父类无参构造,可在子类构造方法中省略。调用父类有参,必须显示声明且必须在子类构造方法的第一行
访问控制
方法重写
finnal
finnal修饰类 不可被继承 例如String
finnal修饰方法 可以被子类继承, 但不能被子类重写
finnal修饰变量, 只能赋一次值
finnal修饰引用时, 地址不能变, 但地址里的内容可以改变
引用类型转换及instanceof
instanceof关键字
判断引用名实际指向的对象,其所属类型是否为右边的类型名,返回boolean
类型结果
instanceof详解好文章
https://segmentfault.com/a/1190000038391136
抽象 abstract
如果一个类中存在抽象方法,该类必须声明为抽象类
但抽象类中可以包含,也可以不包含抽象方法
抽象类和普通类区别:
抽象类必须使用abstract修饰符
抽象类相对普通类,多了包含抽象方法的能力
抽象类相对普通类,失去了实例化创建对象的能力
抽象类和普通类相同点:
符合继承关系特点,能够使用多态机制
子类可以重写从抽象类继承的方法
实例化子类对象需要借助父类构造器实现父类部分的初始化
接口 interface
接口不是类,而是另外一种引用数据类型,他没有构造方法, 注意: 没有构造方法
接口不能实例化对象,但可以指向实现类对象
接口允许多继承(即一个接口可以继承多个接口)
注意事项:
接口多态应用时,编译看左边,运行看右边
即接口引用只能调用接口中包含的方法,成功调用的是重写以后的方法
接口中
数据成员默认 public static final
修饰
方法默认public abstract
修饰
接口实现
注意事项:
重写方法的访问权限修饰符可以被扩大,但是不能被缩小,
而接口中的方法默认由public abstract
修饰
因此: 实现接口方法时, 必须声明访问权限为public
方法抛出异常类型的范围可以被缩小,但是不能被扩大
内部类
枚举
包装类
Object
Onject类有哪些方法?
Object()
构造方法
getClass()
clone()
hashCode()
equals()
toString()
notify()
notifyAll()
wait()
错题
? hashcode和equals的关系?
知乎的一篇好文章
https://zhuanlan.zhihu.com/p/364011883
简单总结:
hashcode的特性:
-
一致性(不变性) 无论调用多少次,都应该返回一样的结果
-
如果equals返回为true那么hashcode也应该相等
-
如果两个对象的equals返回为假,那么hashCode有可能相等,但是如果散列的足够好,那么通常来说hashCode()也不应该相等
-
重写equals通常也一定要重写hashcode(尤其将自定义类作为HashMap中的key和使用HashSet时,必须重写)
map如何判断key是否重复?if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k)))) return e;
先比对象的hash(hash相同->大概率是相同地址,但也可能是不同地址(hash冲突)),然后用==比较地址,相同则key相同,不同再使用equals确认是否相同。
所以,如果重写了equals方法,但没重写hashcode,可能造成hashcode不相同(地址不相同,但实际两个对象的属性相同),出现重复的key。同时HashSet借助HashMap实现,
Object类中所定义的public method
String
String对象是不可变的, 一旦创建,值不能修改。
常量池: 和对象一样,位于堆内存中(注意:是常量池位于堆内存中)。
什么情况下创建变量会指向常量池,什么时候在堆中新建?
使用String s = new String()
和 String s= str + *
(*指"123"或str=“123”)的方式会单独在堆中创建,也就是使用new或创建时使用了已有对象,都会在堆中新建。
使用String s = “。” + “。。”
和 直接String s = “。。。”
会放入常量池
String的.length()和所占的字节数有关吗?
集合
List
ArrayList 初始化扩充次数
Set
Map
HashMap
底层借助哈希表实现, 不能保证存取顺序一致
如果key为自定义类,必须重写hashcode()和equals()
特点:
键唯一,值可重复,无序,线程不安全,键和值允许使用null
自定义排序
异常
异常分类
- RuntimeException 也称unchecked exception 编译期间不会检查, 运行时自动抛出
- checked exception 编译时检查, 必须显示处理, 否则无法通过编译
异常抛出
- 自动抛出
- 手动抛出
例如throw new RuntimeException("")
,可以是Java内置异常类,也可是自定义异常类
异常处理
- 方法声明throws (可抛出多个)
- 捕获并处理try、catch、finally
错题
哪种异常是需要显式捕获或者声明的?
编译异常,包括:
IOException, ClassNotFoundException,SQLException, NoSuchMethodException, InterruptedException
IO
Java IO 体系图 https://blog.csdn.net/xiaojin21cen/article/details/104712206
知乎梳理文章 https://zhuanlan.zhihu.com/p/258344840
字节流 Stream结尾
字符流 Writer/Reader结尾
节点流 & (包装流/增强流/处理流)
JVM
JVM内存模型
各个线程独有的:
1 程序计数器
与线程生命周期相同,记录正在执行的虚拟机字节码指令地址,如果时native方法则为空(undefined),用于并发线程间切换的恢复现场和继续执行。
2 Java虚拟机栈
用于存储局部变量表,操作数栈
共享部分:
3 堆区
4 方法区/元空间
5 本地方法栈
错题
Java Native Interface (JNI) 是Java平台的一个特性,它提供了一种Java程序可以调用本地编写的代码(通常是C或C++代码)的机制。通过使用JNI,Java程序可以调用本地代码实现一些高性能、底层操作,例如操作系统的原生功能、硬件设备的驱动程序等。
JLP(Java Language Processor)是Java编译器,负责将Java源代码编译成字节码。JLW(Java Lightweight UI Toolkit)是Java平台上的一个用户界面工具包,用于创建图形用户界面(GUI)应用程序。JIT(Just-In-Time)编译器是Java平台的一种编译器,它可以将Java字节码动态编译成本地机器码,以提高程序的执行速度。
多线程
什么是多线程
线程创建的三种方式
线程状态
线程有几种状态?
刚创建好的线程对象,就是出于NEW的状态
线程启动后,会出于RUNNABLE状态,其包含俩种情况
就绪状态
,此时这个线程没有运行,因为没有抢到CPU的执行权
运行状态
,此时这个线程正在运行中,因为抢到CPU的执行权
JavaAPI中没有定义就绪状态和运行状态,而是统一叫做RUNNABLE(可运行状态),课程中为了能更加清楚的描述问题,会用上就绪状态和运行状态
线程多次抢到CPU执行权,"断断续续"把run方法执行完之后,就变成了TERMINATED状态(死亡)
之所以"断断续续"的运行,是因为每次抢到CPU执行权的时候,只是运行很小的一个时间片,完了之后还要重新抢夺下一个时间片,并且中间还有可能抢不到的情况
这就是一个线程经历的最基本的状态变化。
其他的状态都是线程在Running的时候,线程中调用了某些方法,或者触发了某些条件,导致这个线程进入到了阻塞状态(上面介绍的三种阻塞情况)
sleep
线程执行了sleep方法后,会从RUNNABLE状态进入到TIMED_WAITING状态
TIMED_WAITING阻塞结束后,线程会自动回到RUNNABLE状态
join
threadxxx.join(long t)
有传参数t则插队t ms
没传则插队到threadxxx执行结束
线程执行了join()方法后,会从RUNNABLE状态进入到WAITING(无限期等待)状态线程执行了join(long million)方法后,会从RUNNABLE进入到TIMED_WAITING(有限期等待)状态
线程安全问题
如果有多个线程,它们在一段时间内,并发访问堆区中的同一个变量(含写入操作),那么最终可能会出现数据和预期结果不符的情况,这种情况就是线程安全问题。
线程安全问题都是由全局变量
及静态变量
引起的
若每个线程中对全局、静态变量只有读
操作,而无写操作
,一般来说,线程是安全的
若多个线程同时执行写操作,就很可能出现线程安全问题,此时需要考虑线程同步技术。
线程同步
同步代码块
例:
class TicketRunnable2 implements Runnable {
//待售票数量
private int num = 50;
//准备锁对象【多个线程必须使用相同锁对象】
Object mutex = new Object();
@Override
public void run() {
while(true) {
//同步代码块:固定书写格式,需要使用同一把锁
//线程执行流程:
// 1.线程成功抢占到共享资源mutex(上锁成功),才能进入代码块执行
// 其他抢占资源失败的线程,则进入阻塞状态
// 2.同步代码执行完成,该线程自动释放共享资源(解锁)
// 其他线程由阻塞转入就绪状态,重新抢占资源(上锁)
synchronized (mutex) {
//如果待售数量 小于0,跳出循环,线程结束
if(num <= 0) break;
//输出信息:模拟卖票
String name = Thread.currentThread().getName();
System.out.println(name + " 正在卖票,编号:" + num);
//编号自减
num--;
//每隔50ms 销售 一张票【sleep放下面是为了更好的输出效果】
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
public class Test16_CodeBlock {
public static void main(String[] args) {
Runnable r = new TicketRunnable2();
Thread t1 = new Thread(r,"1号窗口");
Thread t2 = new Thread(r,"2号窗口");
Thread t3 = new Thread(r,"3号窗口");
t1.start();
t2.start();
t3.start();
}
}
注意,要实现线程同步,必须满足下面2个条件:
所有线程都需要参与线程同步
所有线程必须使用同一个锁对象
同步方法
同步方法可以是普通成员方法,也可以是static静态方法
普通成员同步方法,默认锁对象为this,即当前方法的调用对象
static静态同步方法,默认锁对象是当前类的字节码对象(类名.class)
线程通信
Object方法wait(), notify,notifyall()
wait()
notify
notifyall()
线程池
线程池7个参数
- corePoolSize 核心线程数
- maximumPoolSize 最大线程数
- keepAliveTime 空闲线程存活时间
- unit 时间单位
- workQueue工作队列
- threadFactory线程工厂
- handler 拒绝策略
线程池执行流程
乐观锁、悲观锁
错题
Java线程池的关注要素
线程池7个参数详解: https://blog.csdn.net/Anenan/article/details/115603481