Java基础回顾

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能够继承和重写
默认、无修饰符的只用相同包下的子类能够继承和重写

多态

多态的表现形式

  1. 编译时多态
    方法重载:
    必须改变参数列表,即参数的类型和个数不同,或类型和个数相同但顺序不同(也算重载)
    可以修改返回类型,但只修改返回类型不算重载。
  2. 运行时多态
    1. 方法重写
      外壳不变,核心重写!
      方法名和参数列表要完全相同,返回类型可以修改
      访问权限只能扩大不能缩小
      异常可以缩小(更加确定)不能更大(超出原异常范围)
    2. 接口多态
      一个类实现了某个接口,那么可以通过接口类型的引用来引用该类的对象。这样,一个接口引用可以指向实现了该接口的多个不同类的对象,从而实现了接口类型的多态性。

重写与重载的区别

在这里插入图片描述

构造方法

一般使用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的特性:

  1. 一致性(不变性) 无论调用多少次,都应该返回一样的结果

  2. 如果equals返回为true那么hashcode也应该相等

  3. 如果两个对象的equals返回为假,那么hashCode有可能相等,但是如果散列的足够好,那么通常来说hashCode()也不应该相等

  4. 重写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

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值