实战Java程序设计易忘知识点
2021/9/19 9:35:07
本文主要是介绍实战Java程序设计易忘知识点,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
一、数据类型和运算符
1.1 成员变量(实例变量)的默认初始值
数据类型 | 初始值 |
---|---|
int | 0 |
char | ‘\u0000’ |
double | 0.0 |
boolean | false |
1.2 基本数据类型
- 数值型:byte(1)、short(2)、int(4)、long(8)、float(4)、double(8)
- 字符型:char(2)
- 布尔型:boolean(1)
1.3 二元运算符(+、-、*、/、%)运行规则
整数运算
- 如果两个操作数有一个是long型,那么结果也是long型
- 如果没有long型,结果为int,即使操作数全为short、byte,结果也是int
浮点运算
- 如果两个操作数有一个是double,那么结果就是double
- 只有两个操作数都是float,结果才是float
取模运算
- 其操作数可为浮点数,一般用于整数,结果为整数
1.4 位运算符
运算符 | 说明 |
---|---|
~ | 取反 |
& | 按位与 |
| | 按位或 |
^ | 按位异或 |
<< | 左移运算符,相当于除以2 |
>> | 右移运算符,相当于乘以2 |
1.5 运算符优先级问题
二、控制语句
2.1 switch语句中的表达式数据类型
switch结构中的表达式,只能是以下六种数据类型之一:
byte、short、char、int、枚举类型、String
无论哪个版本的JDK,都是不支持 long,float,double,boolean 这个一定要注意!
2.2 循环结构的分类
- 当型:先判断条件(布尔表示式)是否成立再去执行语句,例如while和for循环两个结构
- 直到型:先执行语句,在判断布尔表示式,例如:do-while结构,另外注意do-while的结构,分号
do { 循环体 }while(布尔表达式);
2.3 break语句和continue语句
- break语句用于强行退出循环,不执行循环中剩余的语句
- continue语句用在循环语句体中,用于终止某次循环过程,即跳过循环体中尚未执行的语句,接着进行下一次是否执行循环的判断。
- continue语句用在while、do-while循环中时,continue立刻提到循环首部。continue语句用在for循环中时,跳到for循环的迭代因子部分。
2.4 语句块
2.4.1 格式
{ 代码块 }
2.4.2 注意
- 作为一个整体,是要内被一起执行的。
- 语句块可以被嵌套在另一个语句快中,但是不能在两个嵌套的语句内声明同名的变量
- 语句块可以使用外部的变量,而外部不能使用语句块中定义的变量,语句块中的变量作用于仅限于语句块
2.5 方法的重载、
方法的重载是指一个类中可以方法名相同,但参数不同的方法。调用时,会根据不同的参数自动匹配对应的方法。
2.5.1 构成方法重载的条件
- 不同的含义:形参类型、形参个数、形参顺序
- 返回值不同的不构成方法的重载
2.6 递归结构
2.6.1 递归结构的组成
-
定义递归头:解答“什么时候不调用自身方法”–>就是递归的结束条件。
-
递归体:解答“什么是否需要调用自身方法”
-
例子:递归求n!
static long factorial(int i){ if(n == 1){ return 1;//递归头 }else{ return n*factorial(n-1);//递归体 } }
2.6.2 递归的评价
简单是递归的优点之一。但是递归会占用大量的系统堆栈,内存耗用多,在递归调用层多时速度比循环慢得多。
任何使用递归解决的问题也能用迭代解决,在高性能要求下,尽量避免使用递归转而使用迭代
三、Java面向对象编程基础
3.1 面向对象和面向过程思想
3.1.1概念
面向对象和面向过程都是对软件分析,设计和开发的一种思想,两者都贯穿于软件分析、设计和开发的各个阶段,对应面向对象就分别称为面向对象的分析(OOA)、面向对象的设计(OOD)和面向对象的编程(OOP)。
3.1.2 面向对象和面向过程的特点
- 面向过程:当我们用面向过程的思想思考问题时,首先要思考“怎么按步骤实现?”,并将步骤对应成方法,一步一步最终完成,它适合简单任务,不需要过多协作的情况
- 面向对象:面向对象跟契合人的思维模式。人们首先思考的是“怎么设计这个事物?”例如思考造车,就先思考“车怎么设计?”而不是“怎样按步骤造车”的问题。
- 面向对象有三大特征:封装、继承、多态,而面向过程只有封装。
- 面向对象可以帮助人们从宏观上把握,从整体上分析整个系统。但是,具体到部分微观操作的(就是一个个方法)实现的,仍然需要用面向过程的思路去实现的。
3.1.3 面向对象的思考方式
在遇到复杂的问题时,先从问题中找到名词,然后确定这些名词哪些可以作为类,在根据问题需求来确定类的属性和方法,最后确定类之间的关系。
3.2对象和类的概念
- 对象是具体的事物;类是对对象的抽象
- 类可以看成一类对象的模板,对象可以看做该类的一个具体实例
- 类是用于描述同一类型对象的一个抽象概念,类定义了这一类对象所应具有的公共属性和方法
3.2.1 对象属性的默认值及作用域
属性的作用是这个类体。定义成员变量时,可以对其进行初始化,如果不对其初始化,Java将使用默认值初始化
数据类型 | 默认值 |
---|---|
整型 | 0 |
浮点型 | 0.0 |
字符型 | ‘\u0000’ |
布尔型 | false |
引用型 | null |
3.3 对象的内存分析
3.3.1 Java虚拟机的内存模型
栈的特点如下:
- 栈是方法执行的内存模型。每个方法调用时都会创建一个栈帧(存储变量、操作数、方法出口等)
- JVM为每个线程都创建一个栈(线程私有),用于存放该线程执行方法的信息(实际参数、局部变量)
- 栈的存储特性是“先进后出,后进先出”,是一个连续的内存空间,运算速度快
堆的特点如下:
- 堆用于存储创建好的对象和数组(数组也是对象)
- JVM只有一个堆,线程共有
- 堆是一个不连续的内存空间,分灵活,但运算速度快
方法区的特点如下:
- JVM只有一个方法区。线程共有
- 方法区实际上也是堆,只是专门来存储类、常量的相关信息
- 用来存放程序中永远不变或唯一的内容,如类信息对象(class对象)、静态变量、字符串常量等
3.4 构造器
3.4.1 构造器的误区
- java通过new关键字调用构造器
- 构造器虽然有返回值,但是不能定义返回值类型(返回值类型肯定时本类),不能再构造器中使用return返回某个值
- 没有定义构造器,系统会自动定义无参构造器,否则不自动添加
- 如果构造器的形参和类的属性名相同,需要用this关键字进行区分
- 对象的创建并不是完全有构造器负责创建的
3.5 垃圾回收机制
3.5.1 容易造成内存泄露的操作
- 创建大量无用对象
- 静态集合类的使用
- 各种连接对象(I/O流对象,数据库连接对象,网络连接对象)为关闭‘
- 监听器的使用
3.6 参数传值机制
Java的方法中,所有参数都是“值传递”,传递的是值的副本
- 基本数据类型参数的传值:传递的是值的副本,副本改变不会影响“原件”
- 应用数据类型的参数:传递的也是值的副本,但是引用类型指的是“对象的地址”,因此,副本和原参数都是指向了同一个地址,改变“副本指向地址对象的值”,也就意味着原参数指向对象的值发生了改变
3.7 JDK中常用的包
包名 | 说明 |
---|---|
java.lang | 包含一些语言的核心类,如String、Math、Integer、System和Thread,提供常用的功能 |
java.awt | 包含了构成抽象窗口工具集(abstract window tooklkits)的多个类,这些类被用来构建和管理应用程序的图形用户界面 |
java.net | 包含执行与网络相关操作的类 |
java.io | 包含提供多种输入输出的类 |
java.util | 使用的工具类,如系统特性,使用与日期,日历相关的函数等 |
第五章、Java面向对象编程进阶
5.1、继承的使用
- 对象 instanceof 类:判断对象是否是类的实例
- 子类获得父类的全部属性和方法,除了父类构造器(但能通过super访问父类构造器)
5.1.1 子类重写父类方法的条件
- “==”:方法名和参数列表相同
- “<=”:返回值类型和声明异常类型,子类小于等于父类
- “>=”:访问权限,子类大于等于父类。private -> default -> protect -> public
- 方法的重写是实现多态的必要条件
5.1.2 继承树追溯
- 属性和方法:从当前类不断向上找属性或方法,直到找到为止,找不到编译出错。
- 构造器的执行:从最顶级的父类构造器执行到当前类构造器
- 对象的创建->代码块、静态代码块、构造器的执行顺序:
父类静态初始化块–>子类静态初始化块–>父类初始化块–>子类初始化块–>父类构造方法–>子类构造方法
##@# 5.2 hashcode的作用
hashcode代表对象的地址说的是对象在hash表中的位置,物理地址说的对象存放在内存中的地址。HashCode的存在主要是为了查找的快捷性,HashCode是用来在散列存储结构中确定对象的存储地址的(后半句说的用hashcode来代表对象就是在hash表中的位置)
5.2 equals方法和==
- “==”比较双方是否相同。
- 如果是基本数据类型则表示值相等
- 如果是引用数据类型,则代表地址(hashcode)相等,即代表同一对象
- equals()方法定义为“对象的内容相等”。
- Object的equals方法默认比较两个对象的hashcode,即是同一个对象的引用时返回true,否则返回false。
- JDK提供了一些类,比如String、Date、包装类,重写了Object的equals方法,使用这些类的equals方法为x.equals(y),当x和y所引用的对象是同一类对象且属性内容相等时(并不一定是相同对象,都是通过new出来便是不同对象)返回true,否则返回false。
- 一个对象可以有多个引用
5.3 super,final关键字
- super作用:通过super关键字可以访问被子类覆盖的父类中的属性和方法,在子类构造器中,super关键字总是第一位,所以当执行构造器时,先执行父类构造器。
- final作用
- 修饰变量:一旦赋予初值,无法改变
- 修饰方法:该方法不可被子类重写,但是可以被重载
- 修饰类:修饰的类不能被继承,比如Math、String类
5.4 封装
5.4.1 封装的优点
- 提高代码的安全性
- 提高代码的复用性
- 高内聚:封装细节,便于修改内部代码,提高可维护性
- 低耦合:简化外部调用,便于使用者使用,便于扩展和协作
5.4.2 封装的实现-访问控制符
修饰符 | 同一个类 | 同一个包 | 子类 | 所有类 |
---|---|---|---|---|
private | √ | |||
default | √ | √ | ||
protect | √ | √ | √ | |
public | √ | √ | √ | √ |
5.4.3 封装的使用细节
类的属性的处理如下
- 一般使用private访问权限
- 提供相应的get/set方法来访问属性,这些方法通常是public修饰的,以提供对属性的赋值和读取操作。boolean变量的get方法是is开头的,比如 public boolean isFlag()
- 只用于本类的辅助性方法可以用private修饰,希望其他类调用的方法用public修饰。
5.5 多态(统一方法+同一父类的不同子类=不同行为)
5.5.1多态的注意事项
- 多态是方法的多态不是属性的多态
- 多态存在的条件:继承,方法重写,父类引用指向子类对象
5.6 对象的转型
- 向上转型:父类引用指向子类对象,引用变量只能调用编译类型的方法,也就是只能调用父类和子类中共同拥有的方法和属性,否则将会抛出异常。这个属于自动类型转换
- 向下转换:将引用变量转换为运行时类型
5.7 抽象类的使用要点
- 有抽象方法一定是抽象类
- 抽象类不能实例化
- 抽象类可以包含属性、方法和构造器,但不能通过构造器实例化,只能用来被子类调用
- 抽象类只能被用来继承
- 抽象方法子类必须实现
5.8 接口的定义说明
接口定义格式:[访问修饰符] interface 接口名 [extends 父接口1,父接口2…]
- 访问修饰符:只能是public 或默认设置
- 接口名:采用和类名相同的命名机制
- extends:接口可以多继承
- 常量:接口中的属性只能是常量,总是以public static final修饰,不写也是
- 方法:接口中的方法只能是public abstract ,即使省略也是public abstract
5.8.1 接口的注意事项
- 接口不能创建实例,可用于声明引用变量类型
- JDK1.7之前,接口中只能包含静态常量和抽象方法,不能有构造器、普通方法和普通属性
- JDK1.8之后,接口中包含普通的静态方法
5.8.2 面向接口编程
面向过程编程(Procedure Oriented、简称PO) 和 面向对象编程(Object Oriented、简称OO) 我们一定听过,然而实际企业级开发里受用更多的一种编程思想那就是:面向接口编程(Interface-Oriented)!
接口这个概念我们一定不陌生,实际生活中最常见的例子就是:插座!
我们只需要事先定义好插座的接口标准,各大插座厂商只要按这个接口标准生产,管你什么牌子、内部什么电路结构,这些均和用户无关,用户拿来就可以用;而且即使插座坏了,只要换一个符合接口标准的新插座,一切照样工作!
5.9 内部类
5.9.1 内部类的作用
- 内部类提供了更好的封装,只能由外部类通过创建内部类对象访问,
5.9.2 内部类的分类
- 成员内部类
- 静态内部类:外部类可以通过静态内部类.名字的方式访问静态内部类的静态成员
- 非静态内部类:内部类可以访问外部类所有方法和属性,但反过来不行
- 匿名内部类:格式:new 父类构造器(参数)\接口(),无构造方法
- 局部内部类:作用于仅限于方法内部
5.10 String类
5.10.1 常量池
- 符号引用和直接引用的概念
在java中,一个java类将会编译成一个class文件。在编译时,java类并不知道引用类的实际内存地址,因此只能使用符号引用来代替。比如org.simple.People类引用org.simple.Tool类,在编译时People类并不知道Tool类的实际内存地址,因此只能使用符号org.simple.Tool(假设)来表示Tool类的地址。而在类装载器装载People类时,此时可以通过虚拟机获取Tool类 的实际内存地址,因此便可以既将符号org.simple.Tool替换为Tool类的实际内存地址,及直接引用地址。 - 全局字符串常量池(String Pool)
全局字符串常量池中存放的内容是在类加载完成后存到String Pool中的,在每个VM中只有一份,存放的是字符串常量的引用值(在堆中生成字符串对象实例) - class文件常量池(Class Constant Pool)
class常量池是在编译时每个class都有的,在编译阶段,它存放的是常量(文本字符串、final常量等)和符号引用 - 运行时常量池(Runtime Constant Pool)
运行时常量池是在类加载完成后,将每个class常量池中的符号引用转存到运行时常量池中。也就是说,每个class都会有一个运行时常量池,类在解析之后,将符号引用替换成直接引用,与全局常量池中的引用保持一致。
5.10.2 String类的常用方法
六、异常机制
6.1 异常的概念
异常(Exception)是指程序运行过程中出现的非正常现象,例如用户输入错误、除数为了0、需要处理的文件不存在、数组下标越界等
6.2 异常类的概念
在Java的异常处理机制中,引进了很多用来描述和处理异常的类,成为异常类。异常类定义中包含了该类异常的信息(异常的是什么)和对异常进行处理的方法
6.3 什么是异常处理
异常处理就是指程序在出现问题时依然可以正确执行完
6.4 Java如何处理异常
Java是采用面向对象的方式处理异常的,在处理过程中:
- 抛出异常:指在执行一个方式时,如果发生异常,则这个方法生成代表该异常的一个对象,异常对象中包含了异常类型和异常出现时的程序状态等异常信息,停止当前执行路径,并把异常对象提交给JRE
- 捕获异常:在方法抛出异常之后,运行时系统将转为寻找合适的异常处理器(exception handler)。潜在的异常处理器是异常发生时依次存留在调用栈中的方法的集合。当异常处理器所能处理的异常类型与方法抛出的异常类型相符时,即为合适的异常处理器。运行时系统从发生异常的方法开始,依次回查调用栈中的方法,直至找到含有合适异常处理器的方法并执行。当运行时系统遍历调用栈而未找到合适 的异常处理器,则运行时系统终止。
6.5 异常的分类
- error
- Exception
- 运行时异常:此类异常是由编程错误(程序员)引起的,比如空指针异常、数组下标越界、类型转换异常,其产生比较频繁,因此是由系统自动检测并将它们交给缺省的异常处理程序(用户可不必对其处理),用户通常通过增加“逻辑处理来避免这些异常”
- 可检查异常:所有不是运行时异常的异常都是可检查异常(不是由编程引起,文件找不到,没有找到该数据库表等等),比如IOException、SQLException等,这类异常在编译时就必须做出处理,否则无法通过编译。
6.6 不同异常的处理态度
对于运行时异常、错误或可查异常,Java技术所要求的异常处理方式有所不同。
-
运行时异常: 由于运行时异常的不可查性,为了更合理、更容易地实现应用程序,Java规定,运行时异常将由Java运行时系统自动抛出,允许应用程序忽略运行时异常。
-
error:对于方法运行中可能出现的Error,当运行方法不欲捕捉时,Java允许该方法不做任何抛出声明。因为,大多数Error异常属于永远不能被允许发生的状况,也属于合理的应用程序不该捕捉的异常。
-
可检查异常:对于所有的可查异常,Java规定:一个方法必须捕捉,或者声明抛出方法之外。也就是说,当一个方法选择不捕捉可查异常时,它必须声明将抛出异常。
能够捕捉异常的方法,需要提供相符类型的异常处理器。所捕捉的异常,可能是由于自身语句所引发并抛出的异常,也可能是由某个调用的方法或者Java运行时 系统等抛出的异常。也就是说,一个方法所能捕捉的异常,一定是Java代码在某处所抛出的异常。简单地说,异常总是先被抛出,后被捕的。
6.7 异常处理的方式
- 捕获异常:try-catch-finally
- 抛出异常:throws(在不知道如何处理该异常时使用)
6.7.1 try-catch-finally语句块的执行过程
- 程序首先执行可能发生异常的try语句块。如果try语句没有出现异常,则执行finally语句块
- 如果try语句出现异常,则中断执行以下代码,并根据异常的类型跳到对应的catch语句执行处理;catch语句执行完成后,程序会继续执行finally语句块
注意事项:
1. 即使try和catch中有return语句,finally语句块也会执行,只是在执行finally后才执行return
2. 只有在执行finally前遇到System.exit(0),finally才会不执行
七、数组
7.1 数组的见解
数组变量是属于引用类型, 数组也可以看做对象,数组中的每个元素相当于该对象的成员变量。数组本身就是对象,由于java中的对象是在堆中存储的,因此数组 是在堆中存储的
7.2 数组的初始化方式
- 静态初始化,定义数组的同时就为数组元素分配空间并赋值,形如:int [ ] a = {1,2,3}
- 动态初始化,数组的定义域为数组元素分配空间不能够赋值的操作分开进行,形如:int [ ] a = new int[2],a[0] = 1,a[1] = 2
- 数组的默认初始化,数组是引用类型,它的元素相当于类的实例变量,因此数组一经分配空间,其中的每个元素也被按照实例变量相同的方式隐式初始化。比如
int a[ ] = new int[2]:默认值是0,0. boolean[ ] b = new boolean[2],默认值是false,false String [ ] s = new String[0],默认值是null,null
7.3 java.util.Arrays类
JDK提供了java.util.Arrays类包含了常用的数组操作,比如排序、查找、填充、打印内容等
八、常用类
8.1 基本数据类型的包装类
8.1.1 包装类的作用
- 方便涉及到对象的操作
- 可用于基本数据类型、包装类、字符串之间的相互转换
8.1.2 包装类的空指针问题
Integer i = null ; int j = i;
8.1.3 包装类的缓存问题
整型、char型所对应的包装类在自动装箱时,对于-128-127之间的值会进行缓存处理,目的是提高效率。
缓存处理的原理为:如果数组在-128-127(1字节),那么在类加载时就已经为该区间的每个数组创建了对象,并将这256个对象缓存到一个名为cache的数组中,每个自动装箱过程发生时(或者手动调用了valueOf方法),就会判断该数据是否在该空间,如果有则直接获取,如果不在则通过new创建
该赋值方式报出空指针异常问题。因为对象i没有指向任何对象
8.1.4 总结
- 自动装箱调用的是valueOf方法,不是new Integer()
Integer i = Integer.ValueOf(100)
- 自动拆箱调用的是xxxValue()方法
int j = i.intValue()
8.2 字符串相关类
String类、StringBuilder类、StringBuffer类是三个与字符串相关的类。String类对象代表不可变字符串序列,StringBuilder和StringBuffer代表可变字符串序列。
8.2.1 String
- String类无法改变的原因:
private final char value[];
上面是字符串的底层源码,字符串的全部内容一次性存储到数组中,而数组的类型定义为final,所以无法改变字符串的值
8.2.2 StringBuild和StringBuffer
- StringBuild和StringBuffer可改变的原因
char value[]
它们的底层源码显示,也是通过数组实现,但是这两个数组没有final修饰,所以可以改变。两者的区别如下:
- StringBuffer:JDK1.0版本提供的类,线程安全,做线程同步检查,效率较低
- StringBuilder:JDK1.5版本提供的类,线程不安全,不做线程同步检查,效率较高,建议采用
StringBuild和StringBuffer的常用方法
- 重载的public StringBuilder append(…)方法,尾部添加字符串返回自身
- public StringBuilder delete(int start,int end)删除start到end-1范围字符串,返回自身
- public StringBuilder deleteCharAt(int index)删除指定位置的char,返回自身
- 重载的public StringBuilder insert(…)指位置上插入字符串,返回自身
- public StringBuilder reverse()将字符串逆序,返回自身
- public String toString()返回数据中的字符串表示形式
- 和String类含有相同类似的方法
- public int indexOf(String str)
- public int indexOf(String str,int fromIndex)
- public String subString(int start)
- public String subString(int start,int end)
- public int length()
- char charAt(int index)
8.3 时间处理相关类
时间是单向的并且是唯一的,所以需要一把刻度尺来表达和度量时间。在计算机世界,人们把1970年1月1日00:00:00定为基准时间。Java用long类型的变量来表示时间
long now = System.currentTimeMillis();
- 构造方法
Date() 分配 Date 对象并初始化此对象,以表示分配它的时间(精确到毫秒)。以本机时间为准。
Date(long date) 分配 Date 对象并初始化此对象,以表示自从标准基准时间(称为“历元(epoch)”,即 1970 年 1 月 1 日 00:00:00 GMT)以来的指定毫秒数。例:Date date1=new Date(10000000000L); 指历元后的10000000000毫秒所表示的时间。 - 常用方法
boolean after(Date when) 测试此日期是否在指定日期之后。
boolean before(Date when) 测试此日期是否在指定日期之前。
int compareTo(Date anotherDate) 比较两个日期的顺序。 如果参数 Date 等于此 Date,则返回值 0;如果此 Date 在 Date 参数之前,则返回小于 0 的值;如果此 Date 在 Date 参数之后,则返回大于 0 的值。
boolean equals(Object obj) 比较两个日期是否相等。
long getTime() 返回自 1970 年 1 月 1 日 00:00:00 GMT 以来此 Date 对象表示的毫秒数。
void setTime(long time) 设置此 Date 对象,以表示 1970 年 1 月 1 日 00:00:00 GMT 以后 time 毫秒的时间点。
String toString() 把此 Date 对象转换为以下形式的 String: dow mon dd hh:mm:ss zzz yyyy 。
8.3.1 DateFormat和SimpleDateFormat 日期格式转换器
date输出的日期格式类型是默认类型,所以需要SimpleDateFormat 来自定义日期的格式。
默认格式:yy-MM-dd aK:m
8.3.2 Calendar日历类
Calendar日历类是一个抽象类,为人么提供了关于日期计算的相关功能,例如年、月、日、分、秒的展示和计算。GregorianCalendar是Calendar的一个具体子类,提供了世界上大多数国家或地区使用的标准日历系统
8.3 Math类
java.lang.Math提供了一系列用于科学计算的静态方法,其方法的参数和返回值类型一般为double型。当需要更加强大的数学计算能力时,如计算高等数学中的相关内容,可以用Apache commons下面的Math类库
8.3.1 Math类的常用方法
- 求最大值、最小值和绝对值
- 求整运算
- 三角函数运算
- 指数运算
8.3.2 java.util.Random类的常用方法
- protected int next(int bits):生成下一个伪随机数。boolean nextBoolean():返回下一个伪随机数,它是取自此随机数生成器序列的均匀分布的boolean值。
- void nextBytes(byte[] bytes):生成随机字节并将其置于用户提供的 byte 数组中。
- double nextDouble():返回下一个伪随机数,它是取自此随机数生成器序列的、在0.0和1.0之间均匀分布的 double值。
- float nextFloat():返回下一个伪随机数,它是取自此随机数生成器序列的、在0.0和1.0之间均匀分布float值。
- double nextGaussian():返回下一个伪随机数,它是取自此随机数生成器序列的、呈高斯(“正态”)分布的double值,其平均值是0.0标准差是1.0。
- int nextInt():返回下一个伪随机数,它是此随机数生成器的序列中均匀分布的 int 值。
- int nextInt(int n):返回一个伪随机数,它是取自此随机数生成器序列的、在(包括和指定值(不包括)之间均匀分布的int值。
- long nextLong():返回下一个伪随机数,它是取自此随机数生成器序列的均匀分布的 long 值。
- void setSeed(long seed):使用单个 long 种子设置此随机数生成器的种子
8.4 java.io.File类
File类来代表文件或目录。在开发中读取文件、生成文件、删除文件、修改文件的属性时经常会用到该类。
8.4.1 FIle类的基本用法
- FIle类的常见构造器:public File(String pathname)
- File类访问属性的方法
方法 | 说明 |
---|---|
public boolean exists() | 文件是否存在 |
public boolean isDerectory() | 是否是目录 |
public bookean isFile() | 是否是文件 |
public long lastModified() | 返回最后修改时间 |
public long length() | 返回文件大小 |
public String getName() | 返回文件名 |
public String getPath() | 返回文件的目录路径 |
- File类创建文件或目录的方法
方法 | 说明 |
---|---|
createNewFile() | 创建新的File |
delete() | 删除File对应的文件 |
mkdir() | 创建一个目录,中间某个目录缺失,创建则失败 |
mkdirs() | 创建多个目录,也会逐层创建缺失目录 |
- 创建文件例子
先得到一个FIle对象再用该对象调用方法File f = new File("a.txt"); f.createNewFile();
九、容器(集合)
9.1 Collection接口的方法(List和Set共有方法)
- size():返回集合中元素的个数
- add(Object obj):向集合中添加一个元素
- addAll(Colletion coll):将形参coll包含的所有元素添加到当前集合中
- isEmpty():判断这个集合是否为空
- clear():清空集合元素
- contains(Object obj):判断集合中是否包含指定的obj元素
- ① 判断的依据:根据元素所在类的equals()方法进行判断
- ②明确:如果存入集合中的元素是自定义的类对象,要去:自定义类要重写equals()方法
- constainsAll(Collection coll):判断当前集合中是否包含coll的所有元素
- rentainAll(Collection coll):求当前集合与coll的共有集合,返回给当前集合
- remove(Object obj):删除集合中obj元素,若删除成功,返回ture否则
- removeAll(Collection coll):从当前集合中删除包含coll的元素
- equals(Object obj):判断集合中的所有元素 是否相同
- hashCod
e():返回集合的哈希值 - toArray(T[] a):将集合转化为数组
- ①如有参数,返回数组的运行时类型与指定数组的运行时类型相同。
- iterator():返回一个Iterator接口实现类的对象,进而实现集合的遍历。
- 数组转换为集合:Arrays.asList(数组)
9.2 List接口
9.2.1 List接口的特点和常用方法
List是可重复有序的集合,除了包含Collection接口的方法,还增加了和顺序(索引)相关方法。List接口的实现类由ArrayList、LinkedList和Vector
方法 | 说明 |
---|---|
void add(int index,Object element) | 指定位置插入元素 |
Object set(int index,Object element) | 修改指定位置的元素 |
Object get(int index) | 获取指定位置的元素 |
Object remove(int index) | 删除指定位置的元素 |
int indexOf(Object o) | 返回第一个匹配的元素位置 |
int lastIndexOf(Object o) | 返回最后一个匹配元素的位置 |
9.2.2 ArrayList的特点和底层实现
ArrayList的底层是数组实现的,其特点是查询效率快,增删效率低,线程不安全。在List的多个实现类中一般使用数组来处理业务。
- ArrayList的底层存储结构
private transient Object[] elementData;
从ArrayList的底层存储结构可以,长度没有固定设置final,所以可以存放任意数量的对象,而扩容的本质就是通过定义新的更大数组,并将旧数组中的内容赋值到新数组来实现扩容。ArrayList的Object数组初始化长度为10。
9.2.3 LinkedList的特点和底层实现
LinkedList底层用双向链表来实现存储,其特点是查询效率低,增删效率快,但线程不安全。双向链表也叫双链表,是链表的一种,它的每个数据节点中都有两个指针,分别指向前一个节点和后一个节点。
- LinkedList的底层源码实现
transient的作用:就是让某些被修饰的成员属性变量不被序列化
public class LinkedList<E> extends AbstractSequentialList<E> implements List<E>,Deque<E>,Cloneable,java.io.Serializable private transient Entry<E> header = new Entry<E>(null,null,null); private transient int size = 0; public LinkedList(){ header.next = header.previous = header; } //链表节点 private static Entry<E>{ E element; Entry<E> next; Entry<E> previous; Entry(E element, Entry<E> next, Entry<E> previous){ this.element = element; this.next = next; this.previous = previous; } }
9.2.4 Vector向量
Vector底层是一个长度可以动态增长的对象数组,它的相关方法都进行了线程同步,因此线程安全效率低,例如,indexOf()方法增加了synchronized同步标记
public synchronized int indexOf(Object o,int index){}
9.2.5 如何选择Vector、ArrayList和LinkedList
- 需要线程安全,用Vector
- 不存在线程安全问题并且查找较多时,用ArrayList
- 不存在线程安全问题并且增删较多,用LinkedList
9.3 Map接口
Map接口用于存储键值对结构信息。Map接口的实现类由HashMap、TreeMap、HashTable和Properties等。
9.3.1 Map接口的常用方法
方法 | 说明 |
---|---|
Object put (Object key,Object value) | 存放键值对 |
Object get(Object key) | 获取指定键的值对象 |
Object remove(Object key) | 删除指定的键值对 |
boolean containsValue(Object value) | 判断容器中是否包含键值对 |
int size() | 包含键值对的数量 |
boolean isEmpty() | Map是否为空 |
void putAll(Map map) | 将map中的所有键值对存放到Map对象中 |
void clear() | 清空Map对象的所有键值对 |
9.3.2 HashMap和HashTable
HashMap采用散列算法来实现的,它是Map接口最常用的实现类。由于底层采用哈希表来存储数据,因此要求键不能重复,新的键值对会替换旧的键值对。HashMap在查找、删除、修改等方面效率高。
- HashMap和HashTable的区别
HashMap:线程不安全,效率高。允许key或value为null
HashTable:线程安全,效率低。不允许key或value为null - HashMap底层实现详解
HashMap底层实现采用了哈希表,这是一种非常重要的数据结构。哈希表的基本结构是“数组+链表”
public class HashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>,Cloneable,Serializable{ //核心数组默认初始化的大小为16(数组必须为2的整数幂) static final int DEFAULT_INTTIAL_CAPACIIY = 16; //负载因子(核心数组被占用0.75开始扩容) static final float DEFAULT_LOAD_FACTOR = 0.75f; transient Entry[] table; static class Entry<K,V> implements Map.Entry<K,V>{ final K key; V value; final int hash; Entry(int hash,K k,V v,Entry<K,V> n){ value = v;//值对象 key = k;//键对象 next = n;//下一个节点 hash = h;//键对象的hash值 } }
十、多线程技术
10.1 多线程的基本概念
10.1.1 程序的概念
程序是一个静态概念,一般对于操系统中的一个可执行文件,比如手机软件,当我们双击进入酷狗的可执行文件,将会加载该程序到内存中执行它,由此就产生"进程(正在执行的程序)”
10.1.2 进程的概念
执行中的程序叫做“进程”,这是一个动态的概念,现代的操作系统都k可以同时启动多个进程。进程的特点如下:
- 进程是程序的一次动态执行过程,占用特定的地址是空间
- 每个进程由3部分组成:CPU、Data、Code。每个进程都是独立的,保有自己的CPU时间、代码和数据。即便用同一份程序产生好几个进程,它们都有这三样东西,这造成的缺点是浪费内存,CPU负担重
- 多任务操作系统将CPU时间动态规划分别每个进程,操作系统同时执行多个进程,每个进程独立运行。
10.1.3 进程与线程的区别
- 进程是动态的,有自己的生命周期,而程序只是指令的集合,是静态的,没有执行的含义。
- 没有建立进程的程序不能作为1个独立单位得到操作系统的认可。
- 1个程序可以对应多个进程甚至一个进程都没有,但1个进程只能对应1个程序
10.1.4 线程的概念及特性
一个进程产生多个线程。线程与多个进程可以共享操作系统的某些资源,同一个进程的多个线程也可以共享此进程的某些资源(例如代码和数据),所以线程又被称为轻量级线程。线程特点如下:
- 一个进程内部的一个执行单元,它是程序中一个单一得到顺序控制流程
- 一个进程可拥有多个并行的线程
- 一个进程中的多个线程共享相同的内存单元/内存地址空间,可以访问相同的变量和对象,而且它们从一个堆中分配对象并进行通信、数据交换和同步操作。
- 由于线程间的通信是在同一个地址空间进行的,所以不需要额外的通信机制
- 线程的启动、中断和消亡所消耗的资源非常少
10.1.5 进程与线程的区别
- 线程可以看做是轻量级的进程,属于同一个进程的线程共享代码和数据空间,每个线程有独立的运行栈和程序计数器,
- 进程是资源分配的单位,线程是调度和执行的单位
- 系统在运行的时候会为每一个进程分配不同的内存区域,但是不会为线程分配内存区域(线程所使用的资源是它所属的进程的资源),线程组只能共享资源,也就是说,线程处理在运行时占用CPU资源,其他资源只能通过共享进程来获取。
10.2 线程的状态和生命周期
线程创建之后,我么必须掌握线程生命周期知识以相关状态的切换方法。
10.2.1 线程状态
一个线程对象的生命周期需要经历5个状态,分别如下
- 1、新生状态
new出来的线程对象就是处于新生状态,处于新生状态的线程有自己的内存空间,此时还没有获得CPU的资源,通过调用start方法进入就绪状态。 - 2、就绪状态
就绪状态的线程已具备了两运行条件,但是还没有被分配到CPU,处于“线程就绪队列”,等待系统为其分配CP,一旦获取CPU,线程就进入运行状态并且自动调用run方法。线程进入就绪状态的方式:- 新建线程:调用start方法,进入就绪状态
- 阻塞线程:阻塞解除不会立即获取CPU资源,所以进入就绪状态
- 运行线程:调研yield方法,直接进入就绪状态
- 运行线程:JVM将CPU资源从本线程切换到其他线程
- 3、运行状态
在运行状态的线程执行其run方法,直到因调用其他方法导致线程终止。或等待某资源产生阻塞或完成任务死亡。如果过在给定的时间片段内没有执行结束,线程便进入就绪状态 - 4、阻塞状态
阻塞状态是指暂停一个线程的执行以等待某个条件的发生(如需要获取某个资源)。如下原因会导入线程进入阻塞状态- 执行sleep(int time)方法,使当前线程睡眠进入阻塞状态,时间到便进入就绪状态
- 执行wait()方法,使当前线程进入阻塞状态当使用notify()方法唤醒这个线程后,它进入就绪状态
- 当线程执行时,某个操作进入阻塞状态,例如执行I/O流操作(read()和write()方法本身就是阻塞方法)。只有当引起该操作阻塞的原因消失后才进入就绪状态
- join()线程联合:当某个线程等待另一个线程执行结束并能继续执行时,使用join()方法
- 5、死亡状态
线程生命周期的最后阶段,当线程进入该阶段后,就无法回到其他状态,进入死亡状态原因如下:- 线程执行完run()方法里面的全部工作
- 线程被强制终止,如通过stop()或destroy()方法来终止程序
10.3 线程的常用方法和优先级
10.3.1 线程的常用方法
方法 | 说明 |
---|---|
isAlive() | 判断线程是否终止 |
getPriority() | 获得线程的优先级 |
setPriority() | 设置线程的优先级 |
setName() | 设置线程的名字0 |
getName() | 获取线程的名字 |
currentThread() | 获取当前线程 |
10.3.2 线程的优先级
处于就绪状态的线程,会进入“就绪队列”等待JVM来挑选。
线程的优先级用数字表示,范围从1-10,一个线程的默认优先级是5.,数字越大优先级越高
- int getPriority():获取线程的优先级
- void setPriority():设置线程的优先级
10.4 线程同步
在处理多线程问题时,如果多个线程同时访问同一个对象,并且某些线程还想修改这个对象时,就需要用到“线程同步”机制
10.4.1 线程同步的概念
线程同步其实就是一种等待机制,多个需要同时访问一个对象的线程进入这个对象的等待池线程队列,等待前面的线程使用完毕,下一给线程再使用。
10.4.2 实现线程同步
通过private关键字可以保障数据对象只能通过方法访问,所以只需要针对方法提出一套机制即可。这套机制就是使用synchronized关键字,它包括两种用法:synchronized方法和synchronized快
- 案例1:多线程操作同一个对象(未使用线程同步)
public class Class_11_9 { public static void main(String[] args) { Account account = new Account(1000,"小白"); Drawing drawing1 = new Drawing(100,account);//定义取钱线程对象 Drawing drawing2 = new Drawing(200,account);//定义取钱线程对象 Drawing drawing3 = new Drawing(300,account);//定义取钱线程对象 drawing1.start();//儿子取钱 drawing2.start();//女儿取钱 drawing3.start();//老婆取钱 } } /*简单的银行账户*/ class Account{ int money; String name; public Account(int money,String name){ this.money = money; this.name = name; } } /*模拟提款操作*/ class Drawing extends Thread{ int drawingNum;//要取出多少钱 Account account;//要取钱的账户 int expenseTotal;//总共取的钱数 public Drawing(int drawingNum,Account account){ super(); this.drawingNum = drawingNum; this.account = account; } @Override public void run() { if ((account.money - drawingNum) < 0){ return; } try { Thread.sleep(2000);//判断完成后阻塞。其他线程开始执行 } catch (InterruptedException e) { e.printStackTrace(); } account.money = account.money - drawingNum; expenseTotal = expenseTotal+drawingNum; System.out.println(this.getName()+"--账户余额:"+account.money); System.out.println(this.getName()+"--共取出了:"+expenseTotal); } }
- 案例2:多线程操作同一个对象(使用线程同步)
这篇关于实战Java程序设计易忘知识点的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2025-01-11有哪些好用的家政团队管理工具?
- 2025-01-11营销人必看的GTM五个指标
- 2025-01-11办公软件在直播电商前期筹划中的应用与推荐
- 2025-01-11提升组织效率:上级管理者如何优化跨部门任务分配
- 2025-01-11酒店精细化运营背后的协同工具支持
- 2025-01-11跨境电商选品全攻略:工具使用、市场数据与选品策略
- 2025-01-11数据驱动酒店管理:在线工具的核心价值解析
- 2025-01-11cursor试用出现:Too many free trial accounts used on this machine 的解决方法
- 2025-01-11百万架构师第十四课:源码分析:Spring 源码分析:深入分析IOC那些鲜为人知的细节|JavaGuide
- 2025-01-11不得不了解的高效AI办公工具API