你都是会点啥技术(四)--- Java

你都是会点啥技术(四)— Java

写在前面的话:到2019年6月份为止,真正使用java有两年了,在大学期间老师教过一遍java(学的不好),看过两三个老师讲解的java视频,每次学习都会有新的体验和收获,也读过《java编程思想》和《深入理解Java虚拟机》,从我对我自己的审视来看,万万不敢说掌握了java这门语言,这次是把java从基础到高级梳理一遍,一方面是对java知识回顾,一方面补充工作中遇到的问题,理论和实践相结合吧, 我想这肯定对我的java功底有一个很大的提升。这次总结也算给自己的java基础画一个小小的句号。。。让我踏着java去开拓更广阔的领域去吧。重点:集合 IO 线程

在这里插入图片描述
链接:https://pan.baidu.com/s/1u58CBOZwX7qZzL1byKlMXQ
提取码:4zk3

一、入门基础及环境搭建

做饭之前需要准备好厨房(生产环境)和厨具,对于java来说,JDK就是做饭的厨房(生产环境),厨具的话流行的有Eclipse,Idea,拿蒸米饭来说,使用高压锅比使用普通铁锅,不仅节省时间而且还不容易糊,还可以让你做米饭事半功倍。
Java初学者必须面对的一步,就是Java JDK的安装及环境变量配置了,这步还没有熟练和掌握的可以参考
JDK下载安装和环境变量作用的详解
一个简单的java程序的基本要素有:标识符、关键字、注释、修饰符、语句、块、类以及 main() 方法。
我们的java程序就是是靠着这些基本要素按照规范组合使用!
拓展点:
1.java程序的运行过程。
2.jdk,jre,jvm区别。
3.判断标识符是否合法。
4.修饰符的作用。
实战:
1.main方法传值。

二、程序设计基础

厨房(生产环境)和厨具准备好了,做一顿美味的菜。佐料是必不可少的,每种佐料都能发挥出它不同的特色味道。java中的佐料有:算术运算符、赋值运算符、逻辑运算符、关系运算符、自增和自减运算符、位运算符、条件运算符,而java中的数据类型相当于不同食物的原料,例如,小麦,水稻…。
这些佐料都用于变量上,变量是一个具有适当的数据类型的数值。
拓展点:
1、变量的作用域,final常量特点
2、数据类型
(1.)基本数据类型:

类型名称关键字占用内存(内存空间)取值范围默认值
字节型byte1字节(8位)-128~1270
短整型short2字节(16位)-32768~327670
整型int4字节(32位)-2147483648~21474836470
长整型long8字节(64位)-9223372036854775808L~9223372036854775807L0L
单精度浮点型float4字节(32位)+/-3.4E+38F(6~7 个有效位)0.0f
双精度浮点型double8字节(64位)+/-1.8E+308 (15 个有效位)0.0d
字符型char2字节(16位)ISO 单一字符集‘u0000’
布尔型boolean1字节(8位)true 或 falsefalse

(2.)数值的隐式类型转化和强制类型或转换
在这里插入图片描述
(3.)数据类型结构
在这里插入图片描述
整数类型等号右边默认是int类型,如果想要表示long类型,需要在值后面加L
浮点型等号右边默认是double类型,如果想要表示float类型,需要在值后面加F
3、char字符型对应的ASCII十进制值
0-9:48-57
A-Z:65-90
a-z:97-122
4、逻辑运算符中的短路与和短路或的特点。
5、 成员变量和局部变量的定义以及生命周期?(面)
局部变量:

  1. 定义在方法中;
  2. 没有默认值,必须自行设定初始值;
  3. 方法被调用时,存在栈中,方法调用结束时局部变量从栈中清除;
    成员变量:
  4. 定义在类中,方法外;
  5. 由系统设定默认初始值,可以不显式初始化;
  6. 所在类被实例化后,存在堆中,对象被回收时,成员变量失效;
三、流程控制语句

当厨房(生产环境),厨具,佐料都准备好后,我们就开始生火做饭了。这个火候怎么把握呢,java中有顺序结构、选择结构和循环结构三种结构来控制火候。
顺序结构:系统则默认自上而下一行一行地执行
选择结构:if和else的组合使用,switch case的使用
循环结构:while,do while,for,foreach(遍历)
终止函数的执行或退出类的方法:return
强行退出循环:break
中止当前迭代的循环,进入下一次的迭代:continue
拓展点:
1.switch 语句中的变量类型可以是: byte、short、int 或者 char。从 Java SE 7 开始,switch 支持字符串 String 类型了,同时 case 标签必须为字符串常量或字面量。

三、字符串处理

当大厨把饭做好之后,接下来就开始美美的拼盘了,java中对字符串进行操作,就像对食物进行加工雕刻拼盘,最后一份色香味俱全的美味就出现了。
定义字符串:String类的特点
连接字符串:+,concat,append
获取字符串长度:str.length()
转换大小写:str.toLowerCase()/str.toUpperCase()转小写/大写非字母不受影响
去空格:str.trim()
截取字符串:substring() 按字符截取
分割字符串:str.split()返回字符串数组
替换字符串:replace(),replaceFirst()和replaceAll()匹配正则表达式进行替换
比较字符串:equals(),equalsIgnoreCase() 比较时不区分大小写,compareTo() 方法用于按字典顺序比较两个字符串的大小,该比较是基于字符串各个字符的 Unicode 值。
查找字符串:indexOf() 方法和 lastlndexOf() 方法用于在字符串中获取匹配字符(串)的索引值,charAt() 方法可以在字符串内根据指定的索引查找字符
利用正则表达式验证字符串
在这里插入图片描述
扩展:
1、String,StringBuffer,StringBuilder的区别
2、String类的特点

四、数字和日期处理

数字和日期这两种食物的拼盘开始啦!
数值运算:Math 类封装了常用的数学运算,提供了基本的数学操作,如指数、对数、平方根和三角函数等,当我们需要进行数值运算的时候就可以直接利用了。
生成随机数:Math中的random() 方法只能产生 double 类型的 0~1 的随机数,Random 类提供了丰富的随机数生成方法,可以产生 boolean、int、long、float, byte 数组以及 double 类型的随机数。
数字格式化:DecimalFormat类对结果进行格式化处理
大数字运算: BigInteger 类是针对整型大数字的处理类,而 BigDecimal 类是针对大小数的处理类,他俩用于高精度计算。
时间日期的处理:Date 类主要封装了系统的日期和时间的信息,并提供了一些日期操作的常用方法。
Calendar类是一个抽象类,它通过getInstance() 方法返回一个 Calendar 对象,
例子:
Calendar calendar = Calendar.getInstance();
calendar.get(Calendar.DAY_OF_YEAR);
Calendar.YEAR:年份。
Calendar.MONTH:月份。(月份从 0 开始,需要加 1)
Calendar.DATE:日期。
Calendar.DAY_OF_MONTH:日期,和上面的字段意义完全相同。
Calendar.HOUR:12小时制的小时。
Calendar.HOUR_OF_DAY:24 小时制的小时。
Calendar.MINUTE:分钟。
Calendar.SECOND:秒。
Calendar.DAY_OF_WEEK:星期几。获取今天星期几(以星期日为第一天)
日期格式化:使用 DateFormat 类和 SimpleDateFormat 类来格式化日期
创建DateFormat对象需要用
DateFormat df=DateFormat.getDatelnstance();日期
DateFormat df=DateFormat.getTimeInstance();时间
SHORT:完全为数字,如 12.5.10 或 5:30pm。
MEDIUM:较长,如 May 10,2016。
LONG:更长,如 May 12,2016 或 11:15:32am。
FULL:是完全指定,如 Tuesday、May 10、2012 AD 或 11:l5:42am CST。

日期和时间相关类

在这里插入图片描述

五、内置包装类

我们把原料小麦加工成面粉,原料水稻加工成大米,相当于对原料进行了一次加工包装。java中也提供原料的包装类,比如int对应Integer,short对应Short等。
Object类:

方法说明
Object clone()创建与该对象的类相同的新对象
boolean equals(Object)比较两对象是否相等
void finalize()当垃圾回收器确定不存在对该对象的更多引用时,对象的圾回收器调用该方法
Class getClass()返回一个对象运行时的实例类
int hashCode()返回该对象的散列码值
void notify()激活等待在该对象的监视器上的一个线程
void notifyAll()激活等待在该对象的监视器上的全部线程
String toString()返回该对象的字符串表示
void wait()在其他线程调用此对象的 notify() 方法或 notifyAll() 方法前,导致当前线程等待
数据类型转换

在这里插入图片描述
Integer类:

方法返回值说明
byteValue()byte以 byte 类型返回该 Integer 的值
shortValue()short以 short 类型返回该 Integer 的值
intValue()int以 int 类型返回该 Integer 的值
toStringString返回一个表示该 Integer值的 String 对象
equals(Object obj)boolean比较此对象与指定对象是否相等
compareTo(IntegeranotherInteger)int在数字上比较两个 Integer 对象,如相等,则返回 0; 如调用对象的数值小于 anotherlnteger 的数值,则返回负值; 如调用对象的数值大于 anotherlnteger 的数值,则返回正值
valueOf(String s)Integer返回保存指定的 String 值的 Integer 对象
parseInt(String s)toString()将数字字符串转换为 int 数值

Float类:

方法返回值说明
byteValue()byte以 byte 类型返回该 Float 的值
doubleValue()double以 double 类型返回该 Float 的值
floatValue()float以float类型返回该Float的值
intValue()int以 int 类型返回该 Float 的值(强制转换为 int 类型)
longValue()long以long类型返回该Float的值(强制转换为long类型)
shortValue()short以 short 类型返回该 Float 的值(强制转换为short类型)
isNaN()noolean如果此 Float 值是一个非数字值,则返回 true,否则返回 false
isNaN(float v)boolean如果指定的参数是一个非数字值,则返回 true,否则返回 false
toStringString返回一个表示该 Float值的 String 对象
valueOf(String s)Float返回保存指定的 String 值的 Float 对象
parseFloatString s)toString()将数字字符串转换为 float 数值

Double类:

方法返回值说明
byteValue()byte以 byte 类型返回该 Double 的值
doubleValue()double以 double 类型返回该 Double 的值
floatValue()float以float类型返回该Double的值
intValue()int以 int 类型返回该 Double 的值(强制转换为 int 类型)
longValue()long以long类型返回该Double的值(强制转换为long类型)
shortValue()short以 short 类型返回该 Double 的值(强制转换为short类型)
isNaN()noolean如果此 Double 值是一个非数字值,则返回 true,否则返回 false
isNaN(float v)boolean如果指定的参数是一个非数字值,则返回 true,否则返回 false
toStringString返回一个表示该 Double值的 String 对象
valueOf(String s)Float返回保存指定的 String 值的 Double 对象
parseFloatString s)toString()将数字字符串转换为 double 数值

Number类: 是一个抽象类,也是一个超类(即父类)。Number 类属于 java.lang 包,所有的包装类(如 Double、Float、Byte、Short、Integer 以及 Long)都是抽象类 Number 的子类。
Character类:

方法描述
void Character(char value)构造一个新分配的 Character 对象,用以表示指定的 char 值
char charValue()返回此 Character 对象的值,此对象表示基本 char 值
int compareTo(Character anotherCharacter)根据数字比较两个 Character 对象
boolean equals(Character anotherCharacter)将此对象与指定对象比较,当且仅当参数不是 null,而 是一个与此对象 包含相同 char 值的 Character 对象时, 结果才是 true
boolean isDigit(char ch)确定指定字符是否为数字,如果通过 Character. getType(ch) 提供的字 符的常规类别类型为 DECIMAL_DIGIT_NUMBER,则字符为数字
boolean isLetter(int codePoint)确定指定字符(Unicode 代码点)是否为字母
boolean isLetterOrDigit(int codePoint)确定指定字符(Unicode 代码点)是否为字母或数字
boolean isLowerCase(char ch)确定指定字符是否为小写字母
boolean isUpperCase(char ch)确定指定字符是否为大写字母
char toLowerCase(char ch)使用来自 UnicodeData 文件的大小写映射信息将字符参数转换为小写
char toUpperCase(char ch)使用来自 UnicodeData 文件的大小写映射信息将字符参数转换为大写

Boolan类:

方法返回值说明
booleanValue()boolean将 Boolean 对象的值以对应的 boolean 值返回
equals(Object obj)boolean判断调用该方法的对象与 obj 是否相等。当且仅当参数不是 null,且与调用该方法的对象一样都表示同一个 boolean 值的 Boolean 对象时,才返回 true
parseBoolean(String s)boolean将字符串参数解析为 boolean 值
toStringString返回表示该 boolean 值的 String 对象
valueOf(String s)Float返回一个用指定的字符串表示的 boolean 值

Byte类:

方法返回值说明
byteValue()byte以一个 byte 值返回 Byte 对象
compareTo(Byte byte)int在数字上比较两个 Byte 对象
doubleValue()double以一个 double 值返回此 Byte 的值
intValue()int以一个 int 值返回此 Byte 的值
parseByte(String s)byte将 String 型参数解析成等价的 byte 形式
toString()String返回表示此 byte 值的 String 对象
valueOf(String s)Byte返回一个保持指定 String 所给出的值的 Byte 对象
equals(Object obj)boolean将此对象与指定对象比较,如果调用该方法的对象与 obj 相等 则返回 true,否则返回 false

System 类:
系统级的很多属性和控制方法都在该类内部,该类构造方法时private的,所以无法创建该类的对象,也就是无法实例化该类,System 类内部的成员变量和成员方法都是 static 的,所以可以方便地进行调用。
System类的3 个静态成员变量,分别是 PrintStream out、InputStream in 和 PrintStream err。
(1、)PrintStream out:标准输出流。
(2、)InputStream in:标准输入流。
(3、)PrintStream err:标准的错误输出流。
System类的成员方法
常用的方法有 arraycopy()、currentTimeMillis()、exit()、gc() 和 getProperty()。
(1、)arraycopy() :该方法的作用是数组复制,即从指定源数组中复制一个数组,复制从指定的位置开始,到目标数组的指定位置结束。
(2、)currentTimeMillis() :该方法的作用是返回当前的计算机时间。
(3、)exit() :该方法的作用是终止当前正在运行的 Java 虚拟机,status 的值为 0 时表示正常退出,非零时表示异常退出。使用该方法可以在图形界面编程中实现程序的退出功能等。
(4、)gc():该方法的作用是请求系统进行垃圾回收。至于系统是否立刻回收,取决于系统中垃圾回收算法的实现以及系统执行时的情况。
(5、)getProperty():

属性名描述
java.versionJava运行时环境版本
java.homeJava安装目录
os.name操作系统的名称
os.version操作系统的版本
user.name用户的账户名称
user.home用户的主目录
user.dir用户的当前工作目录
六、数组处理

数组这一章,不容易理解的就是数组的排序和查找,所以放到数据结构学习博客里面去了。

七、类和对象

本章主要内容就是像做饭的过程,只能在实践中慢慢体会啦!

[public][abstract|final]class<class_name>[extends<class_name>]
[implements<interface_name>]
{
    //定义属性部分
    <property_type><property1>;
    <property_type><property2>;
    <property_type><property3>;//定义方法部分
    function1();
    function2();
    function3();}
上述语法中各关键字的描述如下。

public:表示“共有”的意思。如果使用 public 修饰,则可以被其他类和程序访问。每个 Java 程序的主类都必须是 public 类,作为公共工具供其他类和程序使用的类应定义为 public 类。
abstract:如果类被 abstract 修饰,则该类为抽象类,抽象类不能被实例化,但抽象类中可以有抽象方法(使用 abstract 修饰的方法)和具体方法(没有使用 abstract 修饰的方法)。继承该抽象类的所有子类都必须实现该抽象 类中的所有抽象方法(除非子类也是 抽象类)。
final:如果类被 final 修饰,则不允许被继承。
class:声明类的关键字。
class_name:类的名称。
extends:表示继承其他类。
implements:表示实现某些接口。
property_type:表示成员变量的类型。
property:表示成员变量名称。
function():表示成员方法名称。

八、继承和多态

java三大特性:继承,封装,多态。

封装的优点:
  1. 良好的封装能够减少耦合。

  2. 类内部的结构可以自由修改。

  3. 可以对成员变量进行更精确的控制。

  4. 隐藏信息,实现细节。

继承的特性:

子类拥有父类非 private 的属性、方法。

子类可以拥有自己的属性和方法,即子类可以对父类进行扩展。

子类可以用自己的方式实现父类的方法。

Java 的继承是单继承,但是可以多重继承,单继承就是一个子类只能继承一个父类,多重继承就是,例如 A 类继承 B 类,B 类继承 C 类,所以按照关系就是 C 类是 B 类的父类,B 类是 A 类的父类,这是 Java 继承区别于 C++ 继承的一个特性。

提高了类之间的耦合性(继承的缺点,耦合度高就会造成代码之间的联系越紧密,代码独立性越差)。

多态的优点:
  1. 消除类型之间的耦合关系
  2. 可替换性
  3. 可扩充性
  4. 接口性
  5. 灵活性
  6. 简化性
多态存在的三个必要条件:继承 重写 父类引用指向子类对象

内部类的学习!

九、异常处理

java异常使用笔记总结
在这里插入图片描述

十、集合、泛型和枚举

了解数据结构学习集合会更好一点。

Collection接口框架图

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

Map接口框架图

在这里插入图片描述

十一、反射机制

在程序运行时由用户输入一个类名,然后动态获取该类拥有的构造、属性和方法,甚至调用任意类的任意方法。

类型访问方法返回值类型说明
包路径getPackage()Package 对象获取该类的存放路径
类名称getName()String 对象获取该类的名称
继承类getSuperclass()Class 对象获取该类继承的类
实现接口getlnterfaces()Class 型数组获取该类实现的所有接口
构造方法getConstructors()Constructor 型数组获取所有权限为 public 的构造方法
构造方法getDeclaredContxuectors()Constructor 对象获取当前对象的所有构造方法
方法getMethods()Methods 型数组获取所有权限为 public 的方法
方法getDeclaredMethods()Methods 对象获取当前对象的所有方法
成员变量getFields()Field 型数组获取所有权限为 public 的成员变量
成员变量getDeclareFileds()Field 对象获取当前对象的所有成员变量
内部类getClasses()Class 型数组获取所有权限为 public 的内部类
内部类getDeclaredClasses()Class 型数组获取所有内部类
内部类的声明类getDeclaringClass()Class 对象如果该类为内部类,则返回它的成员类,否则返回 null

在调用 getFields() 和 getMethods() 方法时将会依次获取权限为 public 的字段和变量,然后将包含从超类中继承到的成员实量和方法。而通过 getDeclareFields() 和 getDeclareMethod()只是获取在本类中定义的成员变量和方法。
(1.)访问构造方法

方法名称说明
isVarArgs()查看该构造方法是否允许带可变数量的参数,如果允许,返回 true,否则返回false
getParameterTypes()按照声明顺序以 Class 数组的形式获取该构造方法各个参数的类型
getExceptionTypes()以 Class 数组的形式获取该构造方法可能抛出的异常类型
newInstance(Object … initargs)通过该构造方法利用指定参数创建一个该类型的对象,如果未设置参数则表示采用默认无参的构造方法
setAccessiable(boolean flag)如果该构造方法的权限为 private,默认为不允许通过反射利用 netlnstance()方法创建对象。如果先执行该方法,并将入口参数设置为 true,则允许创建对象
getModifiers()获得可以解析出该构造方法所采用修饰符的整数

(2.)访问方法

方法名称说明
getName().获取该方法的名称
getParameterType()按照声明顺序以 Class 数组的形式返回该方法各个参数的类型
getRetumType()以 Class 对象的形式获得该方法的返回值类型
getExceptionTypes()以 Class 数组的形式获得该方法可能抛出的异常类型
invoke(Object obj,Object…args)利用 args 参数执行指定对象 obj 中的该方法,返回值为 Object 类型
isVarArgs()查看该方法是否允许带有可变数量的参数,如果允许返回 true,否 则返回 false
getModifiers()获得可以解析出该方法所采用修饰符的整数

(3.)访问成员变量

方法名称说明
getName()获得该成员变量的名称
getType()获取表示该成员变量的 Class 对象
get(Object obj)获得指定对象 obj 中成员变量的值,返回值为 Object 类型
set(Object obj,Object value)将指定对象 obj 中成员变量的值设置为 value
getlnt(0bject obj)获得指定对象 obj 中成员类型为 int 的成员变量的值
setlnt(0bject obj,int i)将指定对象 obj 中成员变量的值设置为 i
setFloat(Object obj,float f)将指定对象 obj 中成员变量的值设置为 f
getBoolean(Object obj)获得指定对象 obj 中成员类型为 boolean 的成员变量的值
setBoolean(Object obj,boolean b)将指定对象 obj 中成员变量的值设置为 b
getFloat(Object obj)获得指定对象 obj 中成员类型为 float 的成员变量的值
setAccessible(boolean flag)此方法可以设置是否忽略权限直接访问 private 等私有权限的成员变量
getModifiers()获得可以解析出该方法所采用修饰符的整数
十二、输入/输出流

学习输入/输出流感触最深的就是使用java的多态性。。。

主要的类如下:
 1. File(文件特征与管理):用于文件或者目录的描述信息,例如生成新目录,修改文件名,删除文件,判断文件所在路径等。

 2. InputStream(二进制格式操作):抽象类,基于字节的输入操作,是所有输入流的父类。定义了所有输入流都具有的共同特征。

 3. OutputStream(二进制格式操作):抽象类。基于字节的输出操作。是所有输出流的父类。定义了所有输出流都具有的共同特征。

 4.Reader(文件格式操作):抽象类,基于字符的输入操作。

 5. Writer(文件格式操作):抽象类,基于字符的输出操作。

 6. RandomAccessFile(随机文件操作):一个独立的类,直接继承至Object.它的功能丰富,可以从文件的任意位置进行存取(输入输出)操作。
IO流的分类

根据处理数据类型的不同分为:字符流和字节流
根据数据流向不同分为:输入流和输出流
按数据来源(去向)分类:
1、File(文件): FileInputStream, FileOutputStream, FileReader, FileWriter
2、byte[]:ByteArrayInputStream, ByteArrayOutputStream
3、Char[]: CharArrayReader,CharArrayWriter
4、String:StringBufferInputStream, StringReader, StringWriter
5、网络数据流:InputStream,OutputStream, Reader, Writer

在这里插入图片描述
Java 中的字符是 Unicode 编码,即双字节的,而 InputerStream 是用来处理单字节的,在处理字符文本时不是很方便。这时可以使用 Java 的文本输入流 Reader 类!
所有输入流类都是 InputStream 抽象类(字节输入流)和 Reader 抽象类(字符输入流)的子类。

InputStream 类是字节输入流的抽象类,是所有字节输入流的父类:

在这里插入图片描述
InputStream 类的常用子类如下。
ByteArrayInputStream 类:将字节数组转换为字节输入流,从中读取字节。
FileInputStream 类:从文件中读取数据。
PipedInputStream 类:连接到一个 PipedOutputStream(管道输出流)。
SequenceInputStream 类:将多个字节输入流串联成一个字节输入流。
ObjectInputStream 类:将对象反序列化,操作的对象必须实现序列化接口。

InputStream中的三个基本的读方法

(1.)int read() :读取一个字节数据,并返回读到的数据,如果返回-1,表示读到了输入流的末尾。
(2.)int read(byte[] b) :将数据读入一个字节数组,同时返回实际读取的字节数。如果返回-1,表示读到了输入流的末尾。
(3.)int read(byte[] b, int off, int len):将数据读入一个字节数组,同时返回实际读取的字节数。如果返回-1,表示读到了输入流的末尾。off指定在数组b中存放数据的起始偏移位置;len指定读取的最大字节数。

流结束的判断:方法read()的返回值为-1时;readLine()的返回值为null时。
其它方法

long skip(long n)):在输入流中跳过n个字节,并返回实际跳过的字节数。
int available() :返回在不发生阻塞的情况下,可读取的字节数。
void close() :关闭输入流,释放和这个流相关的系统资源。
void mark(int readLimit):在输入流的当前位置放置一个标记,如果读取的字节数多于readlimit设置的值,则流忽略这个标记。
void reset() :返回到上一个标记。
boolean markSupported() :测试当前流是否支持mark和reset方法。如果支持,返回true,否则返回false。

所有表示字节输出流类的父类是 OutputStream,它也是一个抽象类,同样子类需要重新定义父类的抽象方法:

ByteArrayOutputStream 类:向内存缓冲区的字节数组中写数据。
FileOutputStream 类:向文件中写数据。
PipedOutputStream 类:连接到一个 PipedlntputStream(管道输入流)。
ObjectOutputStream 类:将对象序列化。

方法名及返回值类型说明
void write(int b)向输出流写入一个字节。这里的参数是 int 类型,但是它允许使用表达式,而不用强制转换成 byte 类型。为了提高 I/O 操作的效率,建议尽量使用write() 方法的另外两种形式
void write(byte[] b)把参数 b 指定的字节数组中的所有字节写到输出流中
void write(byte[] b,int off,int len)把参数 b 指定的字节数组中的若干字节写到输出流中。其中,off 指定字节数组中的起始下标,len 表示元素个数
void close()关闭输出流。写操作完成后,应该关闭输出流。系统将会释放与这个输出流相关的资源。注意,OutputStream 类本身的 close() 方法不执行任何操作,但是它的许多子类重写了 close() 方法
void flush()为了提高效率,在向输出流中写入数据时,数据一般会先保存到内存缓冲区中,只有当缓冲区中的数据达到一定程度时,缓冲区中的数据才会被写入输出流中。使用 flush() 方法则可以强制将缓冲区中的数据写入输 出流,并清空缓冲区
Java 的文本输入流 Reader 类,该类是字符输入流的抽象类,即所有字符输入流的实现都是它的子类:

在这里插入图片描述
Reader 类的常用子类如下:
CharArrayReader 类:将字符数组转换为字符输入流,从中读取字符。
StringReader 类:将字符串转换为字符输入流,从中读取字符。
BufferedReader 类:为其他字符输入流提供读缓冲区。
PipedReader 类:连接到一个 PipedWriter。
InputStreamReader 类:将字节输入流转换为字符输入流,可以指定字符编码。

方法名及返回值类型说明
int read()从输入流中读取一个字符,并把它转换为 0~65535 的整数。如果返回 -1, 则表示已经到了输入流的末尾。为了提高 I/O 操作的效率,建议尽量使 用下面两种 read()方法
int read(char[] cbuf)从输入流中读取若干个字符,并把它们保存到参数 cbuf 指定的字符数组中。 该方法返回读取的字符数,如果返回 -1,则表示已经到了输入流的末尾
int read(char[] cbuf,int off,int len)从输入流中读取若干个字符,并把它们保存到参数 cbuf 指定的字符数组中。其中,off 指定在字符数组中开始保存数据的起始下标,len 指定读 取的字符数。该方法返回实际读取的字符数,如果返回 -1,则表示已经 到了输入流的末尾

Writer 类的常用子类如下。
CharArrayWriter 类:向内存缓冲区的字符数组写数据。
StringWriter 类:向内存缓冲区的字符串(StringBuffer)写数据。
BufferedWriter 类:为其他字符输出流提供写缓冲区。
PipedWriter 类:连接到一个 PipedReader。
OutputStreamReader 类:将字节输出流转换为字符输出流,可以指定字符编码。

方法名及返回值类型说明
void write(int c)向输出流中写入一个字符
void write(char[] cbuf)把参数 cbuf 指定的字符数组中的所有字符写到输出流中
void write(char[] cbuf,int off,int len)把参数 cbuf 指定的字符数组中的若干字符写到输出流中。其中,off 指定字符数组中的起始下标,len 表示元素个数
void write(String str)向输出流中写入一个字符串
void write(String str, int off,int len)向输出流中写入一个字符串中的部分字符。其中,off 指定字符串中的起始偏移量,len 表示字符个数
append(char c)将参数 c 指定的字符添加到输出流中
append(charSequence esq)将参数 esq 指定的字符序列添加到输出流中
append(charSequence esq,int start,int end)将参数 esq 指定的字符序列的子序列添加到输出流中。其中,start 指定子序列的第一个字符的索引,end 指定子序列中最后一个字符后面的字符的索引,也就是说子序列的内容包含 start 索引处的字符,但不包括 end索引处的字符
使用过程中比较常用的:

在这里插入图片描述

十三、多线程编程

程序员的懒惰让他们很少有时间去编写没有人需要的代码

1.并发优缺点

并发优点:

发挥多处理的强大的功能
建模的简单性
异步事件的简化处理
响应更加灵敏的用户界面

并发的缺点:

安全性问题
活跃性问题
性能问题
java监视和管理控制台:cmd命名输入 jconsole

2.理解多线程与并发之间的联系与区别
区别:多线程其实并不是多个线程一起执行,而是线程之间因为切换的速度非常的快,所以,我们看起来像不间断的执行。
并行表示的是多个任务同时执行
联系:多线程并不一定是并发,如果是并发执行,那么肯定是多个线程在一块执行。

3.多线程与多进程的联系
进程是资源分配的基本单位
进程中包含多个线程,线程共享进程的资源
线程是处理器调度的基本单位

4.线程垃圾收集器(多线程执行的垃圾收集器,并行执行的垃圾收集器,serial单线程执行的垃圾收集器。)
(单线程一味的收集干活,一直等它干完活就结束,多线程一边想着干活,一边进行线程之间的切换。对于占用内存比较少,回收时间本来就比较短,可以使用单线程的垃圾收集器来进行收集,而它的性能是远比多线程要快的,因此在某些情境下单线程是远比多线程要快的)。
多线程下载并不是多线程提高了速度,也不是多线程的性能提高了,而是,由于外部服务器对资源的限制,为每一个链接分配一定的带宽,而不是将全部带宽分给一个链接,也就是说多线程下载并不是多线程提高了速度,不是多线程的性能提高了,而是多个链接突破了这个远程服务器的限制,也就导致了性能的提高。

5.线程的状态以及各状态之间的转换详解
创建状态:new一个线程后,该进程就处于新建状态,此时由JVM为其分配内存,并初始化成员变量的值。
就绪状态:调用start()方法之后,该线程处于就绪状态。java虚拟机会为其创建方法调用栈和程序计数器等待调度运行。
运行状态:处于就绪状态的线程抢占到CPU,开始执行run()方法的线程执行体,则该线程处于运行状态。
阻塞状态:当处于运行状态的线程失去所占用资源之后,便进入阻塞状态。
死亡状态:线程结束或者出现异常或错误,该线程结束生命周期。

6.线程的初始化,中断和源码分析
Java中线程两种类型:用户线程和守护线程 Thread.setDaemon(false)为用户线程,默认也为用户线程,Thread.setDaemon(true)设置为守护线程。
区别:1.主线程结束后用户线程还会继续运行,JVM存活。
2.如果没有用户线程,都是守护线程,那么JVM结束(随之而来的是所有一切烟消云散,包括所有的守护线程)。
stop()只是让这个线程无限期的等待下去,这个线程所获取得锁、获取得其他资源都没有被释放掉,因此这种方法已经不建议使用了。
interrupt():中断线程,interrupted():查看当前线程是否中断,isInterrupted():判断当前这个线程是否中断。
interrupted()是静态方法:测试当前线程是否已经是中断状态,执行后具有清除状态功能。
isInterrupted()是实例方法:测试线程Thread对象,是否已经是中断状态,但不会清除中断状态。

7-10.线程创建方式(8种)
继承Thread类
实现Runnable接口
带有返回值的线程继承Callable接口,使用FutureTask创建线程对象
内部类3种方式
Timer定时器 timer.schedule(new TimerTask(){},0,1000)
spring注解@Async
Lambda表达式parallelStream并发流

11.了解多线程带来的安全风险
线程安全性问题
活跃性问题 死锁(哲学家吃饭) 饥饿问题(食堂打饭) 活锁(两人过独木桥)
性能问题 线程切换

12.从线程的优先级看饥饿问题

饥饿问题出现的三种情况:

1.优先级高的线程吞噬掉了优先级低的线程的CPU时间片
2.线程被永久堵塞在一个等待进入同步块的状态
3.处于等待状态的线程永远不被唤醒

如何尽量避免饥饿问题:

1.设置合理的优先级
2.使用锁来代替synchronized

13.从java字节码看线程安全问题
java自带分析字节码文件工具javap -verbose name.class文件
线程安全性问题出现的条件:
多线程环境下
多个线程共享一个资源
对资源进行非原子性操作

14.synchronized保证线程安全的原理(理论层面)
内置锁/互斥锁
修饰普通方法:内置锁就是当前实例
修饰静态方法:内置锁就是当前Class字节码文件
修饰代码块:内置锁是放入的对象

15.synchronized保证线程安全的原理(JVM层面)
锁存在的位置:存在对象头中
对象头中的信息:Mark Word,Class Metadata Address,Array Length

Mark Word:

线程Id
Epoch
对象的分代年龄信息
是否是偏向锁
锁标志位

偏向锁:

每次获取锁和释放锁会浪费资源
很多情况下,竞争锁不是有多个线程,而是只有一个线程在使用
只有一个线程在访问同步代码块的场景

轻量级锁:

自旋
多线程使用

重量级锁:

只能有一个锁进入代码块

16.单例问题与线程安全性深入解析
饿汉式单例模式不会出现线程安全问题
懒汉式单例模式使用双重检查加锁和volatile关键字提高CPU性能和避免线程安全性问题

17.理解自旋锁,死锁,重入锁
自旋锁就是代码被多个线程访问时,如果上一个锁不被释放,则下一个线程进入自旋状态。
死锁就是被访问的资源被互相锁住,就进入死锁状态
重人锁就是一个对象被线程访问时,可以进入另一个同步方法,线程不会出现死锁。因为这两个方法锁的是同一个对象。

18.深入理解volatile原理与使用
被volatile修饰的变量,在汇编中多了一个lock指令,lock指令将当前处理器缓存行的数据写回到系统内存中,其他cpu缓存该内存地址的数据失效了,
这就保证了当我们一个线程修改volatile修饰的变量的时候,另一个线程是可见的。
大量使用volatile会使处理器的缓存失效了,也就是说大量使用volatile会降低性能。
对比:volatile只能保证变量的可见性,但是,并不能保证对这个变量所操作的原子性。因此,synchronized可以完全替代volatile,但是volatile并不能取代
synchronized。
volatile保证变量在多个线程之间可见,保证变量的一致性
volatile称为轻量级锁,被volatile修饰的变量,在线程之间是可见的。(可见:一个线程修改了这个变量的值,在另外一个线程中能够读到这个修改后的值)
volatile除了线程之间互斥以外,另一个非常大的作用,就是保证可见性。

19.JDK5提供的原子类操作以及实现原理
AtomicInteger 对整形数据类型原子性操作
AtomicIntegerArray 对整形数组的原子性操作
AtomicReference<> 对实体对象的原子性操作
AtomicIntegerFieldUpdater<> a = AtomicIntegerFieldUpdater.newUpdater(A.class,“old”);对实体对象的字段进行原子性操作,字段需要用volatile操作。

20.Lock接口认识与使用
Lock可以非阻塞的获取锁,能被中断的获取锁,超时获取锁。
提供的方法:lock()加锁 unlock()解锁 lockInterruptibly()中断锁boolean tryLock()获取锁。
Lock需要显示地获取和释放锁,繁琐,但可以使代码更灵活。
Synchronized不需要显示地获取和释放锁,使用简单。
Lock lock = new ReentrantLock();可以方便的实现公平性。

21.手动实现一个可重入锁
思路:继承Lock接口,实现lock()和unlock()方法,声名布尔型isLockd,线程LockBy,整形lockcount三个变量。
操作这三个变量,通过wait()和notify()函数控制线程运行。

22,23.AbstractQueuedSynchronizer(AQS)详解
实现加锁和重入锁

24.公平锁
公平是针对锁的获取而言的,如果一个锁是公平的,那么锁的获取顺序就应该符合请求的绝对时间顺序。

25.读写锁
写 :排他锁
读:共享锁
读-读能共存,
读-写不能共存,
写-写不能共存

26.分析ReentrantReadWriteLock
tryAcquire(int acquires) 互斥锁加锁
tryRelease(int releases) 互斥锁释放
tryAcquireShared(int unused)共享锁加锁
tryReleaseShard(int unused) 共享锁释放

27.锁降级和锁升级
锁降级是指写锁降级为读锁,在写锁没有释放的时候,获取到读锁。
把读锁升级为写锁,在读锁没有释放的时候,获取到写锁。

28.线程安全性问题总结

重复线程安全性问题出现的条件

多线程环境下
具有共享资源
对共享资源进行非原子性操作

解决线程性安全问题的途径

使用synchronized
volatile
JDK原子类
使用Lock

29.线程间的通信
wait()和notify()必须放在同步代码块中。
调用wait()方法时会释放锁,调用notify()时会加锁。释放锁和加锁都是这当前锁释放时拿到的。

30.生产者和消费者问题
生产类实现Runnable,传入对象
消费类实现Runnbale,传入对象
对象类里面做生产和消费,控制产品个数,设置产品数量,然后利用通信控制生产和消费。

31-33.Condition的使用及原理解析有界队列,和源码阅读
Condition的作用是对锁进行更精确的控制,它的await()相当于wait(),它的signal()相当于notify(),它的signalAll()相当于notifyAll()
不同的是它不需要与synchronized捆绑使用,但需要与互斥锁和共享锁捆绑使用。

34.实现数据库连接池
连接池有助于数据库性能的提升
初始化时建立一定个数的连接放到linklist里,获取连接时去池中拿连接,如果池中没有连接则等待,释放一个连接时,可以叫醒获取连接的线程。

35.线程加塞join
语法:j.start();j.join()

36.ThreadLocal用于保存某个线程共享变量
get: 获取ThreadLocal中当前线程共享变量的值。
set: 设置ThreadLocal中当前线程共享变量的值。
remove: 移除ThreadLocal中当前线程共享变量的值。
initialValue: ThreadLocal没有被当前线程赋值时或当前线程刚调用remove方法后调用get方法,返回此方法值。

37-41.并发工具类:CountDownLatch,CyclicBarrier,Semaphore,Exchanger
Semaphore:一个计数信号量
CountDownLatch:一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待。
CyclicBarrier:一个同步辅助类,它允许一组线程互相等待,直到到达某个公共屏障点
Exchanger:方便了两个共同操作线程之间的双向交换
42-44.FuterTask
哎,没理解透,找个好心情再出发: https://blog.csdn.net/codershamo/article/details/51901057
45.Fork/Join框架
拆分处理最后合并,能够发挥多核服务器的优势
ForkJoinTask 实现类 RecursiveTask
class A extends RecursiveTask
@Override
protected Integer compute(){
A a1 = new A();
A a2 = new A();
a1.fork();
a2.fork();
return a1.join() + a2.join();
}
ForkJoinPool pool = new ForkJoinPool();
Future f = pool.submit(new A());
结果:f.get();
46-48.同步容器和并发容器
Vector(线程安全) -----同步容器----> ArrayList(线程不安全)-----并发容器----->CopyOnWriteArrayList
Hashtable(线程安全)-------同步容器----> HashMap(线程不安全)----并发容器----->CopyOnWriteHashMap
并发容器:ConcurrentLinkedQueue
49.java中的阻塞队列BlockingQueue
private BlockingQueue queue = new ArrayBlockingQueue<>(10);
queue.push(1)发送 queue.take()抓取
50.Executors框架
public static void main(String[] args) {
// ExecutorService threadPool = Executors.newFixedThreadPool(10);//分配固定的线程数
ExecutorService threadPool = Executors.newCachedThreadPool();// 根据需要自动建立相应的线程数
for (int i = 0; i < 50; i++) {
threadPool.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
});
}
threadPool.shutdown(); // 关闭线程池
}

十四、网络编程

ServerSocket 类表示 Socket 服务器端,Socket 类表示 Socket 客户端,两者之间的交互过程如下:
服务器端创建一个 ServerSocket(服务器端套接字),调用 accept() 方法等待客户端来连接。
客户端程序创建一个 Socket,请求与服务器建立连接。
服务器接收客户的连接请求,同时创建一个新的 Socket 与客户建立连接,服务器继续等待新的请求。

URLConnection 类来表示与 URL 建立的通信连接,URLConnection 类的对象使用 URL 类的 openConnection() 方法获得.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值