@TOC
JAVA
简历:技术(10W)+ 我的项目(20W)+ 算法(30W) + 业务(50~100W) + 行业视线(上不封顶)
①JavaSE
JAVA背景常识
JDK装置和配置
程序的运行机制
- Java语言是编译型和解释型的联合
![[外链图片转存失败,源站可能有防盗链机制,倡议将图片保留失败,源站可能有防盗a下来img-E8Ie02)(C:\Ue10V-526\011027\AppData\Roaming\Typora\typora-user-images\image-2021480310176152570.pg6
9)(C:\Users\UC241027\AppData\Roaming\Typora\typora-user-images\image-20210310171652570.png)]](https://img-blog.csdnimg.cn/2...
- JVM(Java Virtual Machine):它定义了指令集、寄存器集、构造栈、垃圾收集堆、内存区域,负责java字节码解释运行,边解释边运行,一次编译随处运行。
- JRE(Java Runtime Environment):Java虚拟机、库函数、运行Java应用程序必须的文件。
- JDK(Java Development Kit):蕴含JRE,以及减少编译器和调试器等用于程序开发的文件。
Java装置与配置
- 环境变量Path配置
JAVA_HOME : JAVA装置的目录
Path:%JAVA_HOME%\bin
第一个Java程序
- Java编译的时候,呈现unmappable character for encoding GBK
解决办法:
1、因为零碎默认编码不是utf8,所以要将编译改写为javac -encoding UTF-8 XXX.java就能够失常输入
2、将XXX.java文件另存为-->抉择编码ANSI保留
变量、数据类型、运算符
标识符
- ASCⅡ字符集:12^8 = 256
- Unicode国内字符集:2^16 = 65536
变量
- 变量实质是可操作的存储空间,空间地位是确定的,值不确定;变量名拜访“对应的存储空间”,操作这个“存储空间”存储的值
- 局部变量、成员变量(也称实例变量)和动态变量
数据类型
- boolean类型是4个字节,数组中是1个字节(在内存中占1个字节或4个字节)
- 数字格式化输入
System.out.format("%.3f %.3f\n",r,volume);System.out.printf("%.3f %.3f\n",r,volume);
运算符
- 整数运算:
两数有一个为long,则后果为long。
没有long时,后果为int。即便操作数全为short、byte,后果也是int。
- 浮点运算:
有一个为long,后果为long。
两个为float,后果才为float。
- 取模运算:
个别应用整数,后果是”余数“,”余数“符号和右边雷同。
- 自增、自减
a++ //先赋值,再自增
++a //先自增,再赋值
- 关系运算符
\>、>=、<、<= 仅针对数值类型(byte/short/int/long,float/double 以及char-->0~65535)
- 逻辑运算符
- 位运算符
- 数据类型的转换
整型常量是int类型,然而能够主动转为:byte、short、char。只有不超过对应类型的范畴。
管制语句
- 管制语句分为:程序、抉择、循环;
- 任何软件和程序,实质上都是有"变量、抉择语句、循环语句"组成。
switch语句
- switch语句中case标签在JDK1.5之前必须是整数(long类型除外)或枚举,不能字符串,但在JDK1.7之后容许应用字符串
Scanner类 键盘输入
java中Scanner类nextInt之后用nextLine无奈读取输出
问题呈现起因:
这是因为在调用nextLine()函数前调用了Scanner的另一个函数nextInt()(或是nextDouble())。呈现这种状况的起因是两个函数的解决机制不同,nextInt()函数在缓冲区中遇到“空格”、“回车符”等空白字符时会将空白字符前的数据读取走,但空白字符不会被解决掉,而nextLine()函数是在缓冲区中读取一行数据,这行数据以“回车符”为完结标记,nextLine()会把包含回车符在内的数据提走。所以nextInt()后的nextLine()函数并非读取不到数据,因为nextInt()将“回车符”留在了缓冲区,nextLine()读取时遇到的第一个字符便是“回车符”,所以间接完结了。
解决办法:
在要应用nextLine()前先调用一次nextLine(),这样留在缓冲区的“回车符”就会被解决掉,这时第二个nextLine()函数能够失常读取到数据。
办法
办法重载(overload):理论是齐全不同的办法,只是名称雷同而已,释义:定义多个办法名雷同,但参数不同的办法。
形成办法重载的条件:
- 不同的含意:形参类型、形参个数、形参程序不同
- 只有返回值不同不形成办法的重载(如:int a(String str){}与void a(String str){}不形成办法重载)
- 只有形参的名称不同,不形成办法的重载
- 办法重写的三个要点:
面向对象编程
- 属性用于定义该类或该类对象蕴含的数据或者说动态特色。成员变量能够对其初始化,如果不对其初始化,Java应用默认的值对其初始化。
- 成员变量的默认值
- 结构器4个要点
- JAVA虚拟机内存模型概念
- 容易造成内存透露的操作
①. 创立大量无用对象
②.动态汇合类的应用
③.各种连贯对象(IO流对象、数据库连贯对象、网络连接对象)未敞开
④.监听器的应用
- 对象的申明周期
- 创建对象四步
①.调配对象空间,并将对象成员变量初始化为0或空
②.执行属性值得显式初始化
③.执行构造方法
④.返回对象的地址给相干的变量
- 应用
通过变量援用操作对象
- 回收
对象咩有被变量应用,则被认为是”垃圾“,会被垃圾回收器回收
this、static关键字
this关键字
- 创立一个对象分为四步:
** this的实质是“创立好的对象地址”,在构造方法调用前,对象曾经创立。因而,在构造方法中应用this示意"以后对象"。
- this最常的用法
static关键字
继承
继承的实现
- 继承要点:
instanceof 运算符
instanceof是二元运算符,右边是对象,左边是类;当对象是左边类或子类所创建对象时,返回true;反之为false。
public class Person{ String name; int age; public static void main(String[] args){ Student s = new Student(“AAA”,66); System.out.println(s instanceof Person); System.out.println(s instanceof Student); }}class Student extends Person{}
办法的重写 override
子类通过重写父类的办法,能够用本身的行为替换父类的行为;办法的重写是实现多态的必要条件。
- 办法重写须要合乎三个要点:
final关键字
属性和办法前加final,是不可扩大(继承)和更改的,办法不可重写,但可重载。
- final关键字的作用:
继承和组合
组合不同于继承,更加灵便。
组合的外围是将父类对象作为子类的属性,而后,子类通过调用这个属性来获取父类的属性和办法。
- 组合:排汇或并购
public class Animal{ public static void main(String[] args){ Taidi t = new Taidi(); t.dog.shout(); }}class Dog{ public void shout(){ System.out.println("wangwang...."); }}//组合class Taidi { Dog dog = new Dog(); //Taidi蕴含(排汇)了Dog,所以具备了Dog的属性和办法}
总结:
继承除了代码复用、也能不便咱们对事务建模。”is a“ 关系倡议应用继承,”has a“ 关系倡议应用组合。(如:Student is a Person逻辑就没问题,但Student has a Person就有问题了;笔记本和芯片的关系属于蕴含,则能够应用”has a“)
super关键字
- super 能够看做是间接父类对象的援用。通过super来拜访被子类笼罩的办法或属性。
- 应用super调用一般办法,语句没有地位限度,能够在子类中轻易调用。
- 若构造方法的第一行代码没有显式的调用super()或者this();那么java默认都会调用super(),含意是调用父类的无参数构造方法。super()可省略。
继承树追溯
封装(encapsulation)
- 封装的具体的长处
- 封装的实现---应用拜访控制符
+ protected须要留神的两个细节
多态
多态指的是同一个办法调用,因为对象不同可能会有不同的行为。
- 多态的要点
- 多态的必要三个条件
- 继承
- 重写
- 父类援用指向子类对象
- 类型的强制转化,分编译和运行,编译看右边,编译之后是什么类型就执行什么样的办法;运行看左边。
形象办法和抽象类
abstract润饰的办法,没有办法体,只有申明。定义的是一种"标准",就是通知子类必须要给形象办法提供具体的实现。
- 抽象类的应用要点:
接口 interface
- 面向对象的精华,是对对象的形象,最能体现这一点的就是接口。
- 接口就是比"抽象类"还"形象"的"抽象类"。(abstract)
- 接口就是定规范的,就是要让他人实现的。(public)
- 接口申明办法的时候能够不写public和abstract,默认是有的。
- 接口定义的是不变的,如变量只能定义为常量。能够不写public abtract final来润饰变量,默认是有的。
定义接口的具体阐明:
区别:
- 一般类:具体实现
- 抽象类:具体实现,标准(形象办法)
接口:JDK1.8之前只有标准,但JDK1.8之后新增了静态方法和默认办法
- 默认办法:
默认办法和形象办法的区别是形象办法必须要被实现,因为默认办法有办法体,所以不须要实现,在接口中default必须要写,通过实现类的对象调用。 - 静态方法:
能够在接口中间接定义静态方法的实现。这个静态方法间接从属于接口(接口也是类,一种非凡的类),能够通过接口名调用。
- 默认办法:
接口的多继承
接口齐全反对多继承,和类的继承相似,子接口扩大某个父接口,将会取得父接口中所定义的所有。
字符串String 类详解
字符串String是在办法区的字符串常量池(String Pool)中存储
String 类和常量池
- 常量池分三种:
- String根底
外部类
- 外部类:
- 定义在一个类的外部的类,目标是方便使用外部类的相干属性和办法;
- 外部类只是一个编译时概念,一旦编译胜利,就会成为齐全不同的两个类。
- 外部类作用
- 外部类的分类
- 非动态外部类
//外部类public class Outer { private int age = 10; private void show(){ System.out.println("good!!!"); } //非动态外部类 public class Inner{ private String name = "tom"; private int age = 20; public void showInner(){ System.out.println("Inner.showInner"); System.out.println(age); System.out.println(Outer.this.age); show(); } } public static void main(String[] args) { Outer.Inner inner = new Outer().new Inner(); //通过 new 外部类名().外部类名() 来创立外部类对象 inner.showInner(); }}
- 动态外部类
//外部类public class Outer { private int a = 10; private static int b = 20; //动态外部类 static class Inner{ public void test(){ System.out.println(b); } } public static void main(String[] args) { Outer.Inner inner = new Outer.Inner(); //通过 new 外部类名.外部类名() 来创立外部类对象 inner.test(); }}
- 匿名外部类
适宜那种只须要应用一次的类。
public class AnonymousInnerClass { public void test(A a){ a.run(); } public static void main(String[] args) { AnonymousInnerClass anonymousInnerClass = new AnonymousInnerClass(); //匿名外部类 anonymousInnerClass.test(new A() { @Override public void run() { System.out.println("匿名外部类是没有名字的类,只需应用一次;如果从新调用一次,就会定义新的匿名外部类!"); } }); }}interface A{ void run();}
- 部分外部类
定义在办法外部的,作用域只限于本办法。
public class LocalInnerClass{ public void show(){ //作用域仅限于该办法 class Inner{ public void fun(){ System.out.println("部分外部类的实现!"); } } new Inner().fun(); } public static void main(String[] args){ new LocalInnerClass().show(); }}
数组
数组:雷同类型数据的有序汇合,数组也是对象。
- 数组的四个根本特点
数组初始化
- 1、数组动态初始化
例如:
int[] a = {1,2,3}; //动态初始化根本类型数组
Man[] mans = {new Man(1,1),new Man(2,2)}; //动态初始化援用类型数组
- 2、数组动静初始化
例如:
int[] a = new int[2]; //动静初始化数组,先调配空间
a[0] = 1; //给数组元素赋值
a[1] = 2; //给数组元素赋值
- 3、数组的默认初始化
例如:
int[] a = new int[2]; //默认值:0,0
boolean[] b = new boolean[2]; //默认值:false,false
String[] s = new String[2]; //默认值:null,null
总结:默认初始化---->数组元素相当于对象的属性,恪守对象属性默认初始化的规定。
异样机制
当程序呈现谬误,程序平安的、继续执行的机制。
JAVA罕用类
Wrapper包装类
包装类:能够把根本类型、包装类对象、字符串三者进行互相转化
- 主动装箱和拆箱
- 包装类的缓存问题
当数字在[-128,127]之间的时候,返回缓存数组中的某个元素。
public class Test{ public static void main(String[] args){ //当数字在[-128,127]之间的时候,返回的是缓存数组中的某个元素 Integer i1 = 123; //主动装箱;编译器:Integer i1 = Integer.valueOf(123); Integer i2 = 123; //主动装箱;编译器:Integer i1 = Integer.valueOf(123); System.out.println(i1 == i2); // true;是因为123都是从缓存中取的同一个元素 System.out.println(i1.equals(i2)); // true }}
字符串相干类
String类:不可变字符序列,会产生新对象的。
StringBuilder类:可变字符序列;效率高,然而线程不平安;增加字符序列,返回本身对象。
StringBuffer类:可变字符序列;效率低,然而线程平安;增加字符序列,返回本身对象。
- String 类
public class Test{ public static void main(String[] args){ //编译器做了优化,在编译的时候,左边是字符串常量,不是变量,所以间接将字符串做了拼接 String str1 = "hello" + " java"; //相当于 str1 = "hello java"; String str2 = "hello java"; System.out.println(str1 == str2); //true String str3 = "hello"; String str4 = " java"; //编译的时候不晓得变量中存储的是什么,所以没方法在编辑的时候做优化 String str5 = str3 + str4; System.out.println(str2 == str5); //false }}
- 效率测试
public class Test { public static void main(String[] args) { String str = ""; long num1 = Runtime.getRuntime().freeMemory(); long time1 = System.currentTimeMillis(); for(int i = 0;i < 5000;i++){ str += i; } long num2 = Runtime.getRuntime().freeMemory(); long time2 = System.currentTimeMillis(); System.out.println("String占用内存:" + (num1 - num2)); System.out.println("String占用工夫:" + (time2 - time1)); System.out.println("==================================="); StringBuilder sb = new StringBuilder(""); long num3 = Runtime.getRuntime().freeMemory(); long time3 = System.currentTimeMillis(); for(int i = 0;i < 5000;i++){ sb.append(i); } long num4 = Runtime.getRuntime().freeMemory(); long time4 = System.currentTimeMillis(); System.out.println("StringBuilder占用内存:" + (num3 - num4)); System.out.println("StringBuilder占用工夫:" + (time4 - time3)); System.out.println("==================================="); StringBuffer sb2 = new StringBuffer(""); long num5 = Runtime.getRuntime().freeMemory(); long time5 = System.currentTimeMillis(); for(int i = 0;i < 5000;i++){ sb2.append(i); } long num6 = Runtime.getRuntime().freeMemory(); long time6 = System.currentTimeMillis(); System.out.println("StringBuffer占用内存;" + (num5 - num6)); System.out.println("StringBuffer占用工夫:" + (time6 - time5)); }}
效率测试后果如下:
File类
java.io.File类:代表文件和目录。
枚举
枚举类型隐形地继承自java.lang.Enum。枚举本质上还是类,而每个被枚举的成员本质就是一个枚举类型的实例。他们默认都是public static final润饰的。能够间接通过枚举类型名应用。
enum 枚举名 { 枚举体(常量列表)}
- 特地留神:
汇合(容器)
泛型
泛型简介
泛型是将类型基于一个占位符模式来定义,在泛型中,不能够应用根本类型,只能用对象类型来定义泛型。
- 泛型的益处:
总结一下:
- 类型擦除
编译时采纳泛型写的类型参数,编译器会在编译时去掉。
泛型的应用
- 定义泛型
- 泛型类
泛型类是把泛型定义在类上。
- 泛型接口
泛型接口和泛型类的申明形式统一。泛型接口的具体类型须要在实现类中进行申明。
- 泛型办法
泛型办法是指将办法的参数类型定义成泛型,以便在调用时承受不同类型的参数。类型参数能够有多个,用逗号隔开,如:<K,V>。类型参数个别放到返回值后面。
+ 非静态方法
+ 静态方法
静态方法无法访问类上定义的泛型;如果静态方法操作的援用数据类型不确定的时候,必须要将泛型定义在办法上。
- 泛型办法与可变参数
在泛型办法中,泛型也能够定义可变参数类型。
通配符和高低限定
- 无界通配符
+ 通配符的下限限定
下限限定示意通配符的类型是T类以及T类的子类或者T接口以及T接口的子接口。
+ 通配符的上限限定
上限限定示意通配符的类型是T类以及T类的父类或者T接口以及T接口的父接口。该办法不实用泛型类。
- 泛型总结
容器
数组也是一种容器,能够搁置对象或根本类型数据
- 数组的劣势:是一种简略的线性序列,能够疾速地拜访数组元素,效率高。仅从效率和类型查看的角度讲,数组是最好的。
- 数组的劣势:不灵便。容量须要当时定义好,不能随着需要的辩护而扩容。
总之,容器的底层都是基于数组来实现的。容器中数据都是存储在内存的。
List
List:有序(元素存入汇合的程序和取出的程序统一)、可反复
- ArrayList是List接口的实现类。是List存储特色的具体实现。
- ArrayList底层是用数组实现的存储。特点:查问效率高、增删效率低、线程不平安。
- ArrayList:提早扩容,如要扩容以1.5倍扩容。
Vector
Vector:底层应用数组实现的。线程平安,效率低。Vector的应用与ArrayList是雷同的。初始容量是10,如要扩容以2倍扩容。
Stack
Stack:栈容器,是Vector的一个子类,它实现了一个规范的后进先出(LIFO:Last In First Out)的栈。
- 栈的操作
//栈容器应用案例public class StackTest { public static void main(String[] args) { StackTest st = new StackTest(); st.symmetry(); } //匹配符号的对称性 public void symmetry(){ String str = "...{.....[....(....)....]....}..(....)..[...]..."; //实例化Stack Stack<String> stack = new Stack<>(); //假如修改法 boolean flag = true; //假如是匹配的 //拆分字符串获取字符 for(int i = 0;i < str.length();i++){ char c = str.charAt(i); if(c == '{'){ stack.push("}"); } if(c == '['){ stack.push("]"); } if(c == '('){ stack.push(")"); } //判断符号是否匹配 if(c == '}'||c == ']'||c == ')'){ if(stack.empty()){ flag = false; break; } String x = stack.pop(); if(x.charAt(0) != c){ flag = false; break; } } } if(!stack.empty()){ flag = false; } System.out.println(flag); }}
LinkedList
- 底层用双向链表实现的存储。特点:查问效率低,增删效率高,线程不平安。
- 实现了List接口,所以LinkedList是具备List的存储特色的(有序,元素有反复)
Set
Set特点:无序,不可反复。无序指Set中的元素没有索引,只能遍历查找;不可反复指不容许退出反复的元素。
HashSet
- HashSet:是一个没有反复元素的汇合,不保障元素的程序,线程不平安。容许有null元素;采纳哈希算法实现,底层是用HashMap实现的,HashMap底层应用的是数组与链表实现元素的存储。查问效率和增删效率比拟高。Hash算法也称之为散列算法。
无序:
不反复:
TreeSet
- 通过元素本身实现比拟规定
- 通过比拟器指定比拟规定
Map
Map接口定义了双例汇合的存储特色,它不是Collection接口的子接口。双例汇合的存储特色是以key与value构造为单位进行存储的。
- Map与Collection的区别
HashMap
- HashMap的底层源码
TreeMap
Iterator 迭代器
- Iterator对象的工作原理
Collections工具类
数据结构
数据结构是以某种特定的布局形式存储数据(存储构造上差别)的容器。
- 数据结构逻辑分类
- 线性构造:元素存在一对一的互相关系
线性表、栈、队列、串(一堆数组)等
- 树形构造:元素存在一对多的互相关系
二叉树、红黑树、B树、哈夫曼树等
- 图形构造:元素存在多对多的互相关系
有向图、无向图、简略图等
线性构造
栈构造
栈是一种只能从一端存取数据且遵循"后进先出(LIFO)"准则的线性存储构造
链表构造
链表构造是由许多节点形成的,每个节点都蕴含两局部:
- 链表分类
单向链表
双向链表
双向循环链表
- 链表的特点
- 链表的优缺点
单向链表构造
双向链表构造
树形构造
- 节点
应用树结构存储的每一个数据元素都被称为“结点”。
- 节点的度
某个结点所领有的子树的个数
- 树的深度
树中节点的做大档次数
- 叶子结点
度为0的结点,也叫终端结点。
- 分支结点
度不为0的结点,也叫非终端结点或外部结点。
- 孩子
也可称之为子树或者子结点,示意以后节点上层的间接结点。
- 双亲
也可称之为父结点,示意以后结点的间接下层结点。
- 根节点
没有双亲结点的结点。在一个树形构造中只有一个根节点。
- 先人
从以后结点下层的所有结点。
- 子孙
以后结点上层的所有结点。
- 兄弟
同一双亲的孩子。
二叉树
满二叉树
齐全二叉树
二叉树遍历
正则表达式
Java中正则表达式为String类型,被验证的内容同样为String类型。通过String类中的matches办法实现内容的匹配校验。如:”被验证内容“.matches("正则表达式")
在定义限定内容规定是,如果没有指定长度限定,那么默认长度为1。
内容限定
- 单个字符限定
[a]:示意以后内容必须是字母a
- 范畴字符限定
[a-z0-9]:示意内容能够是a-z之间的任意字母或者0-9之间的任意数字,不分先后
- 取反限定
[^abc]:示意内容不能是a或b或c。
长度限定
长度限定符号
预约义字符
在正则表达式中能够通过一些预约义字符来示意内容限定。目标是为了简化内容限定的定义
组合定义
通过多个内容限定与长度限定来组合定义
常见的正则表达式
| :或者 ,如:a|b (a或b)
\\.:任意字符 ,如:-|\\. (-或任意一个字符)
IO流
- 数据源:提供数据的原始媒介。常见的数据源有:数据库、文件、其余程序、内存、网络连接、IO设施。
- 流:形象、动静的概念,是一连串间断动静的数据汇合。
输出流:数据流从数据源到程序(InputStream、Reader结尾的流)
输入流:数据流从程序到目的地(OutputStream、Writer结尾的流)
- JAVA中四大IO抽象类
InputStream/OutputStream和Reader/Writer类是所有IO类的形象父类
InputStream: 字节输出流
OutputStream: 字节输入流
Reader: 读取的字符流抽象类,数据单位为字符
Writer: 输入的字符流抽象类,数据单位为字符
- Java中流的细分
按流的方向分类:
输出流:InputStream、Reader结尾的流
输入流:OutputStream、Writer结尾的流按解决的数据单元分类:
字节流:以字节为单位获取数据,FileInputStream、FileOutputStream
字符流:以字符为单位获取数据,Reader/Writer结尾的流,如FIleReader、FileWriter按解决对象不同分类
节点流:间接从数据源或目的地读写数据,如:FileInputStream、FileReader、DataInputStream
解决流:也叫包装流,不间接连贯到数据源或目的地,是”解决流的流“。通过对其余流的解决进步程序的性能,如:BufferedInputStream、BufferedReader。
- 通过字节缓冲流进步读写效率
总结:
- File类
File类是Java提供的针对磁盘中的文件或目录转换对象的包装类。一个File对象能够代表一个文件或目录。
文件字节流
通过缓冲区进步读写效率
形式一:
public class FileDemo { public static void main(String[] args) throws Exception{ try(FileInputStream fis = new FileInputStream("images/s1.jpg"); FileOutputStream fos = new FileOutputStream("images/11.jpg"); ){ //创立一个缓冲区 byte[] buff = new byte[1024]; //空间换效率,效率低,但空间节俭。 int len = 0; while((len = fis.read(buff)) != -1){ fos.write(buff,0,len); } fos.flush(); }catch (Exception e){ e.printStackTrace(); } }}
形式二:
public class FileDemo { public static void main(String[] args) throws Exception{ try(FileInputStream fis = new FileInputStream("images/s1.jpg"); FileOutputStream fos = new FileOutputStream("images/11.jpg"); ){ //创立一个缓冲区 byte[] buff = new byte[fis.available()]; //效率换空间,占内存,但效率快 fis.read(buff); fos.write(buff); fos.flush(); }catch (Exception e){ e.printStackTrace(); } }}
通过字节缓冲流进步读写效率
public class FileCopyTools { public static void main(String[] args) { copyFile("images/s1.jpg","images/11.jpg"); } /** * 文件拷贝办法 */ public static void copyFile(String src,String des){ try(BufferedInputStream bis = new BufferedInputStream(new FileInputStream(src)); BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(des)); ){ int temp = 0; while((temp = bis.read()) != -1){ bos.write(temp); } bos.flush(); } catch (Exception e){ e.printStackTrace(); } }}
文件字符流
- 如果一个一个字符读取,后果是Unicode字符,需将后果强转char才能看懂数据内容。
- 如果是字符输入流,创立了两个字符输入流并同时向同一个文件输入内容,默认是会笼罩。除非加参数true,能力追加。
字符缓冲流
字符输出缓冲流字符输入缓冲流
转换流
InputStreamReader/OutputStreamWriter用来实现将字节流转化成字符流。
字符输入流
- PrintWriter: 是节点流,能够间接作用于文件的。
字节数组流
字节数组输出流(ByteArrayInputStream)
- ByteArrayInputStream : 则是把内存的"字节数组对象"当做数据源。
- FileInputStream :是把文件当做数据源。
字节数组输入流(ByteArrayOutputStream)
- ByteArrayOutputStream:将流中的数据写入到字节数组中。
public class ByteArrayOutputStreamDemo { public static void main(String[] args) { ByteArrayOutputStream bos = null; StringBuilder sb = new StringBuilder(); try{ bos = new ByteArrayOutputStream(); bos.write('a'); bos.write('b'); bos.write('c'); byte[] arr = bos.toByteArray(); for(int i = 0;i < arr.length;i++){ sb.append((char)arr[i]); } System.out.println(sb.toString()); }finally{ try{ if(bos != null){ bos.close(); } }catch (Exception e){ e.printStackTrace(); } } }}
数据流
- DataInputStream和DataOutputStream提供了能够存取与机器无关的所有Java根底类型数据(如:int、double、String等)。
数据输入流
//数据输入流public class DataIOStreamDemo { public static void main(String[] args) { try(DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(new FileOutputStream("data.txt")));){ dos.writeChar('a'); dos.writeInt(4); dos.writeDouble(Math.random()); dos.writeUTF("您好"); dos.flush(); }catch (Exception e){ e.printStackTrace(); } }}
数据输出流
读取的程序要与数据输入流写入的程序统一,否则不能读取数据
//数据输出流public class DataIOStreamDemo { public static void main(String[] args) { try(DataInputStream dis = new DataInputStream(new BufferedInputStream(new FileInputStream("data.txt")));){ //间接读取数据,留神:读取的程序要与写入的程序统一,否则不能读取数据 System.out.println("char:" + dis.readChar()); System.out.println("int:" + dis.readInt()); System.out.println("double:" + dis.readDouble()); System.out.println("utf:" + dis.readUTF()); }catch (Exception e){ e.printStackTrace(); } }}
对象流
数据流只能实现对根本数据类型和字符串类型的读写,并不能Java对象进行读写操作(字符串除外),而对象流除了能实现对根本数据类型进行读写操作,还能对Java对象进行读写操作。
- 对象的序列化和反序列化
序列化
对象的序列化:把java对象转换为字节序列的过程。
- 对象序列化的作用
- 序列化波及的类和接口
import java.io.BufferedOutputStream;import java.io.FileOutputStream;import java.io.ObjectOutputStream;//对象输入流实现根本数据类型的输入public class ObjectIOStreamDemo { public static void main(String[] args) { try(ObjectOutputStream oos = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream("data")));){ oos.writeInt(10); oos.writeDouble(Math.random()); oos.writeChar('a'); oos.writeBoolean(true); }catch (Exception e){ e.printStackTrace(); } }}
- 将对象序列化到文件
反序列化
对象的反序列化:字节序列复原为Java对象的过程。
随机拜访流
- 外围办法
多线程
程序:
过程:
- 过程特点
线程:
- 线程和过程的区别
- 并发
- 办法的执行特点()
- 线程的执行办法的特点
- 主线程
+ 主线程的特点
它是产生其余子线程的线程。
它不肯定是最初实现执行的线程,子线程可能在它完结之后还在运行。
- 主线程
在主线程中创立并启动的线程,个别称之为子线程。
线程的创立
通过继承Thread类实现多线程
通过实现Runnable接口实现多线程
线程的执行流程
线程的生命周期
- 新生状态
- 就绪状态
- 运行状态
- 阻塞状态
- 死亡状态
线程的应用
终止线程
import java.io.IOException;public class StopThread implements Runnable{ private boolean flag = true; @Override public void run() { System.out.println(Thread.currentThread().getName() + "线程开始"); int i = 0; while(flag){ System.out.println(Thread.currentThread().getName() + " " + i++); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println(Thread.currentThread().getName() + "线程完结"); } //劝本人他杀形式终止线程,线程能失常完结。 public void stop(){ this.flag = false; } public static void main(String[] args) throws IOException { System.out.println("主线程开始"); StopThread st = new StopThread(); Thread t1 = new Thread(st); //启动线程 t1.start(); System.in.read(); st.stop(); System.out.println("主线程完结"); }}
- 暂停以后线程执行sleep/yield
+ yield 办法的应用
线程联结
- join办法的应用
class A implements Runnable{ @Override public void run() { for (int i = 0; i < 10; i++) { System.out.println(Thread.currentThread().getName() + " " + i); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } }}public class JoinThread { public static void main(String[] args) throws InterruptedException { Thread t = new Thread(new A()); //启动A线程 t.start(); //主线程 for (int i = 0; i < 10; i++) { System.out.println(Thread.currentThread().getName() + " " + i); //当i=2时,主线程期待A线程完结之后再运行 if(i == 2){ t.join(); } Thread.sleep(1000); } }}
Thread类罕用办法
- 获取以后线程名称
- 判断以后线程是否存活
线程优先级
守护线程
- 守护线程的特点:守护线程会随着用户线程死亡而死亡。
- 守护线程与用户线程的区别
线程同步(就是把并行改成串行)
synchronized可阻止并发更新同一个共享资源,实现了同步,然而synchronized不能用来实现不同线程之间的消息传递(通信)。
实现线程同步
- synchronized 关键字应用时须要思考的问题:
> > 
线程同步的应用
应用this作为线程对象锁
在不同线程中雷同对象中synchronized会互斥。
语法结构:
synchronized(this){ //同步代码}
或
public synchronized void accessVal(int newVal){}
应用字符串作为线程对象锁
所有线程在执行synchronized时都会同步。因字符串是不变序列,所以会持有雷同锁。
synchronized("字符串"){ //同步代码}
应用Class作为线程对象锁
在不同线程中,领有雷同Class对象中的synchronized会互斥。
synchronized(XX.class){ //同步代码}
或
synchronized public static void accessVal(){ //同步代码}
应用自定义对象作为线程对象锁
在不同线程中,领有雷同自定义对象中的synchronized会互斥。放在线程中造成互斥锁。
synchronized(自定义对象){ //同步代码}
死锁及解决方案
死锁是因为同一代码块呈现嵌套synchronized造成的,解决办法是避免出现嵌套synchronized语句块。
线程并发合作(生产者/消费者模式)
角色:
生产者:负责生产数据的模块
消费者:负责解决数据的模块
缓冲区:消费者不能间接应用生产者数据,它们之间有个“缓冲区”。生产者将生产好的数据放入“缓冲区”,消费者从“缓冲区”拿要解决的数据。
缓冲区的益处:- wait() 办法:要在synchronized块中调用,该办法执行后,线程会将持有的对象锁开释,并进入阻塞状态,其余须要该对象锁的线程就能够持续运行了。
- notify() 办法:要在在synchronized块中调用,该办法执行后,会唤醒处于期待状态队列中的一个线程
/** * 定义馒头类 */class ManTou{ private int id; public ManTou(int id){ this.id = id; } public int getId(){ return this.id; }}/** * 定义缓冲类 */class SyncStack{ //定义放馒头的盒子 private ManTou[] mt = new ManTou[10]; //定义盒子的suoyin private int index; /** * 放馒头 */ public synchronized void push(ManTou manTou){ while(this.index == this.mt.length){ try { //该办法执行后,线程会将持有的对象锁开释,并进入阻塞状态,其余须要该对象锁的线程就能够持续运行了。 this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } this.notify(); //该办法执行后,会唤醒处于期待状态队列中的一个线程 this.mt[this.index] = manTou; this.index++; } /** * 取馒头 */ public synchronized ManTou pop(){ while(this.index == 0){ try { //该办法执行后,线程会将持有的对象锁开释,并进入阻塞状态,其余须要该对象锁的线程就能够持续运行了。 this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } this.notify(); //该办法执行后,会唤醒处于期待状态队列中的一个线程 this.index--; return this.mt[this.index]; }}/** * 定义生产者线程 */class Producer extends Thread{ private SyncStack ss; public Producer(SyncStack ss){ this.ss = ss; } @Override public void run() { for (int i = 0; i < 10; i++) { System.out.println("生产馒头:" + i); ManTou manTou = new ManTou(i); this.ss.push(manTou); } }}/** * 定义消费者线程 */class Customer extends Thread{ private SyncStack ss; public Customer(SyncStack ss){ this.ss = ss; } @Override public void run() { for (int i = 0;i < 10;i++) { ManTou manTou = this.ss.pop(); System.out.println("生产馒头:" + i); } }}public class ProduceThread { public static void main(String[] args) { SyncStack ss = new SyncStack(); new Thread(new Producer(ss)).start(); new Thread(new Customer(ss)).start(); }}
线程并发合作总结
- 线程通过哪些办法来进行消息传递,总结如下:
下列的办法均是java.lang.Object类的办法,都只能在同步办法或者同步代码块中应用,否则会抛出异样。
网络编程
网络通信协定
OSI七层协定模型:别离是:应用层、表示层、会话层、传输层、网络层、数据链路层、物理层。
TCP/IP协定
应用层、传输层、互联网络层、网络接口层(物理 + 数据链路层)
- 传输过程中,会波及到封装和解封
总结:发送数据必须同时指定IP地址和端口。
#### URL(Uniform Resource Locator)
在www上,每一信息资源都有对立且惟一的地址。URL由四局部组成:协定、寄存资源的主机域名、被迫文件和端口号。
#### Socket
#### TCP和UDP协定
TCP协定
UDP协定
网络编程中罕用类
- InetAddress类:封装计算机的IP地址和域名。没有构造方法,如果要失去对象,只能通过getLocalHost()、getByName()等静态方法创建对象。
- InetSocketAddress类:蕴含IP和端口信息,罕用于Socket通信。此类实现IP套接字地址(IP地址 + 端口号),不依赖任何协定。相比于InetAddress多了端口号。
- URL类:标识了计算机的资源,它是指向互联网“资源”的指针。(IP地址标识了Internet上惟一的计算机)
TCP通信实现
- 申请-响应 模式
Socket类:发送TCP音讯
ServerSocket类:创立服务器
- Socket的编程程序
UDP通信实现
- DatagramPacket:数据容器(封包)的作用
示意数据报包。数据报包用来实现将发送的数据进行封包解决的。