java学习笔记

Dos基础命令

更换盼复:d:

查看当前目录下的文件及文件夹

进入文件夹 cd 文件名字

返回上一级 cd...

清空屏幕:cls

删除文件:del 文件名

删除文件夹: rd 文件夹名字

退出:exit quit

创建文件:copy nul 文件名.文件类型

创建文件夹:mkdir 文件夹名

cmd命令行窗口字符编码切换为UTF-8,命令行中执行:chcp 65001

JAVA 接口文档package包介绍:D:Program FilesJavajdk1.8.0_241jrelib t.jar

一、java概述与环境搭建

  1. java1995年有sum Microsystems 推出,经过24年迭代
  2. JAVA的特点是面向对象、简单、跨平台
  3. 将源文件编译成字节码文件(.class),在交与不同平台进行解释执行。
  4. JVM虚拟机、JRE运行环境、JDK开发环境
  5. DOS 命令 (见开头)
  6. 开发步骤

a) 创建.java源文件

b) 编写程序(class main 、逻辑代码)

c) 编译:javac 文件名.java (文件名.后缀名)

d) 运行:java 类名(无后缀)

  1. 同一个源文件中可以定义多个类
  2. 编译后,每个类都会生成独立的 .class 文件
  3. 一个类中,只能有一个主函数,每个类都可以有自己的主函数。
  4. public修饰的类称为公开类,要求类名必须与文件名称完全相同,包括大小写
  5. 一个源文件,只能有一个public 公开类。

package 包:

作用:类似于文件夹,用于管理字节码(.class)文件。

语法: package 包名;

位置:包名必须写在源文件的第一行

带包编译:javac -d . 源文件名.java

带包运行:java 包名.类名(包名+类名)

 

采用域名倒置规则:www.baidu.com  -->  com.baidu.www

 

二、语言基础:

  1. 前置知识:

什么是内存:内存是瞬时状态下的存储空间,造价高、工业上的设计瓶颈。

java虚拟机(java程序)默认分配到的物理内存是1/8

bit -> Byte -> KB -> MB -> GB -> TB -> PB -> EB -> ZB -> YB -> BB -> NB -> DB -> CB -> XB

    2.变量

变量定义流程:

声明:数据类型 变量名;

赋值: 变量名 =

Java中变量具有严格的数据类型区分

Java语言中,任何一个值,都有其对应类型。

整数类型的取值范围:(默认取值为:int)

 

浮点类型取值范围:(浮点的默认类型:double)

 

单精度:float 将小数存入变量中时需在数值尾部加入“F”:float p= 12.51F;  否则将会报编译错误;

近似值:

float 32bit   1bit 符号位  8bits指数位 23bits尾数位

double 64bit  1bit 符号位  11bits指数位  52bits尾数位

布尔类型:

 

字符类型:

 

字符转义符:       例;    ’   ...

字符串:

 

类型转化:

同类型转换中,需目标类型大于源类型;

强制类型转换中(大的往小的里放),可能会出现精度丢失,

方法:  target a = ( target )b   

short num =123;

byte target = (byte)num;

赋值运算:

包定义:明确该文件的.calss文件结构,必须放在文件的首行; package p1;

引入包: import ...

控制台输入:根据输入的内容进行程序的执行。

import java.util.Scanner;

Scanner inputInfo = new Scanner(System.in);

System.out.println("请输入内容:");

int num = inputInfo.nextInt();   // 输入类型为int;

double num = inputInfo.nextDouble();// 输入类型为小数;

String num = inputInfo.next();// 输入类型为串;

char num = inputInfo.next().charAt(0);// 输入类型为字符;

 

implements 接近于类实现某接口(interface)

定于接口与类的实现:

public interface People{

public void say();

}

public class Chinese implements People{

public void say(){

 System.out.print(‘hello’);

}

}

People chinese = new Chinese()

chinese.sya()

extends的区别,extends 表示对父类的继承,且一个类只可单一继承,可以实现父类,也可调用父类的方法,而且可以重写覆盖父类定义的方法及属性。

implements表示对接口的实现,通过接口关键字‘implements’实现,在接口中声明方法,在子类中实现方法。

当方法需要实现,不可修改,固定为规定的模板时使用implements,只定义接口。而需要被实现,或者可以被修改,拓展性好,用extends ;

函數:

概念:实现特定功能一段代码,可反复使用。

定义语法:

plublic static void FunctionName(String[] args){

}

将需要多次复用的代码,定义在函数中,减少代码量;

函数定义在类的函数内部,与main 相同层级;

数值的比较equals():

java中,进行字符串类型的对比,因字符串为引用地址类型,对比的数据值为内存地址,所以使用“==,将无法获得准确的数值,String.equals() 可对应解决字符串数值比对,其内部源码比对的是源对象,与目标对象的字符长度及每一个下标的数值是否相等;

String.contentEquals();其作用与equals相同,但是其内部将会区分StringBuilder 类型,然后进行对比。

a.equals(b);

a.contentEquals(c);

返回值与返回值类型:

函数调用时,一些情况下无需返回结果,另一些情况下则必须返回结果。

定义语法:

public static 返回值类型 函数名称(形式参数列表){

//函数体

return value;   //返回值

}

数组的创建语法:

//合并数组方法1

int [] newArr = new int[oldArr.length+newArrList.length];

System.arraycopy(oldArr, 0, newArr, 0, oldArr.length);

System.arraycopy(newArrList, 0, newArr, oldArr.length, newArrList.length);

for(int i = 0 ; i <newArr.length;i++) {

System.out.print(newArr[i] +" ");

}

//合并数组方法2

int [] newArr = java.util.Arrays.copyOf(oldArr, oldArr.length+newArrList.length);

System.arraycopy(newArrList, 0, newArr, oldArr.length, newArrList.length);

for(int i = 0 ; i <newArr.length;i++ ) {

System.out.print(newArr[i] + " ");

}

数组的扩容:

Java中数组在声明完长度时候是不可改变原数组的长度的,但可以使用获取原数组的长度,创建新数组时,重新设定新数组的数据内容,并添加新的数据,从而达到数组的扩容功能;

private int[] dilatation(int[] oldArr,int addLenght) {

return  java.util.Arrays.copyOf(oldArr, oldArr.length+addLenght);

}

数组的插入Insert: 将数组指定位置以后的值赋予前一个地址,在将指定位置内容进行覆盖。

void insert( int position , int data ) {

if(stack.length == size) {

stack = dilatation(stack,1);

}

for(int i = size;i > position ; i --) {

stack[i] = stack[i-1];

}

stack[position] = data;

size++;

}

可变长参数:

概念:可接受多个同类实参,个数不限,使用方式与数组相同。

语法:数据类型: ... 形参名   必须放在参数列表最后,且只能存在一个。

传入参数与python 方法类似,默认除开形参个数以外的内容,整合封装到... arr 之中。

数组的排序:

冒泡排序:相邻的两个数值比较大小,之后进行位置的互换

java.util.Arrays.sort(arr);     JDK排序

二维数组创建语法

先声明,在分配空间:

数组类型[][] 数组名;

数组名 = new  数据类型[高维长度][低维长度]

声明并分配空间:

数据类型[][] 数据名 = new 数据类型 [高维长度][低维长度]

声明并赋值:

数据类型[][] 数据名 = new 数据类型[高维长度][];  //不规则数组,自行new 低维数组;

声明并赋值:

数据类型[] 数据名 = {{v1,v2,v3},{v4,v5,v6},{v7,v8,v9}};

double 类型保留2位小数:

String.format(“%.2f”,f);

DecimalFormat df = new DecimalFormat("#0.00")    df.format(f)

NumberFormat nf = NumberFormat.getNumberInstance();  nf.format(f))

DoubleFormat f = new DoubleFormat();      f.m1()

杨辉三角:

public static int[][] yhArr(int rows ) {

// 1

// 1  1

// 1  2  1

// 1  3  3  1

// 1  4  6  4  1

// 1  5  10  10  5  1

int[][] arr = new int[rows][];

for(int i = 0 ; i < rows ;i++ ) {

arr[i] = new int [i+1];

for (int j = 0 ; j <= i ; j++) {

arr[i][j]= (j>0 && i >1 && j!=i)?arr[i-1][j] + arr[i-1][j-1]:1;

}

}

return arr;

}

方法的重载

方法重载(overload)是指方法名称相同,但是形参列表不同(参数类型、参数个数、参数顺序)的方法。调用重载的方法时,Java编译器会根据实参列表寻找最匹配的方法进行调用。

面向对象的思想里,方法重载就是对象的另一种行为存在多种实现过程,就构成了方法重载。

在面向对象中,我们还需要学习到方法(覆盖)override

对象与类:

程序中的对象:

类的定义:

属性:通过变量表示,又称实例变量。

语法:数据类型  属性名;

位置: 类的内部,方法的外部。

方法:通过函数的表示,又称为实例方法。

语法:

public 返回值类型 方法名(形参){

//方法的主体

}

类与对象的关系:

Extends继承中子类的super:

thissuper:

thisjava中指向当前实例,当调用this()是指向的是当前类的super()  (只可在无参情况)

super 指向父类实例;

多态:

概念:父类引用产生多种形态,从而产生多态;

将子类对象当成父类类别看待;

在子类方法覆盖父类方法之后 ,在父类参数中调用被覆盖的方法时 将自动调用子类方法

使用父类作为方法形参实现多态,使方法的参数的类型更加广泛。

使用父类作为方法的返回值实现多态,使方法可以返回不同子类对象。

向上转型(装箱)

父类引用中保留真实子类对象,称为向上转型(即多态核心概念)

Animal pet = new Dog()

想下转型(拆箱)

将父类引用中的真是子类对象,强转回子类本身类型,称为向下转型。

注意:只有转回子类真是类型,才可以调用子类独有的属性和方法。

Dogs pet = (Dog)pet;

判断目标是否是某个类的实例,从而进行对应的拆箱:

pet instanceof Dogs

个人理解:多态也可以理解为多样,在将父类作为参数或者返回值时,根据类的继承关系,在调用父类时,指向的还是原子类对相关,即父类引用指向子类对象。

总结复习

父类的抽象:

程序中的继承:

程序中的继承,是类与类之间的特征和行为的赠与或获得。

两个类之间的继承关系,必须满足is a”的关系。

java为单继承,一个类只能有一个直接父类,但可以多层继承,属性和方法逐级叠加。

不可继承:

访问修饰符:

方法的覆盖:

覆盖原则:


super 关键字:

super this访问属性:

super调用父类有参构造

thissuper

程序的多态:

多态中的方法覆盖:

多态的应用:

类型转换异常:

instanceof关键字:

get/set方法编写:

关键字:

abstract 抽象

什么是抽象:似是而非,像却又不是,具备某种对象的特征,但又不完整。

抽象类:abstract 修饰类,此类不能New对象。

Abstract修饰的类,称为抽象类。抽象类意为不完整的累、不够具体的累,抽象类对象无法独立存在,即不能new对象。

抽象方法:

抽象类中的抽象方法与interface 接口一样,定义的抽象方法必须要子类全部实现,否则子类就不是完整的实例子类。

总结:


@override  方法的覆盖关键字,指覆盖其父级方法,静态方法不可覆盖。

static 静态:

static 声明,将在全局方法区,共同声明同一个方法或属性,全局共用。

静态方法时可以通过类名调用(在调用该方法时,可能从未创建对象)

JAVA中的方法调用分为两种:

  1. 静态分派(静态方法中,允许参数列表不同的重名方法,指静态方法之间的重载)
  2. 动态分派(在具有继承关系的情况下,调用实例方法时,自底向上查找可用的方法版本,指实例方法的覆盖)

方法调用指令5个:

invoke spacial 私有方法、构造方法

invoke interface 接口方法

invoke static 调用静态方法

invoke virtual 调用虚方法()

invoke dynamic 调用动态链接方法

静态方法允许直接访问静态成员

静态方法不能直接访问非静态方法

静态方法中不允许使用this super关键字

静态方法可以继承,不能重写,没有多态。

个人观点为:静态方法属性在初始化时为最优先级,切与其他实例无直接联系,而在动态方法初始完成时,实例方法还未动态生成完成。

编译器可知,运行期不可变。

类加载

JVM首次使用某个类时,需通过CLASSPATH查找该类的 .class文件。

将查找到的class文件,读取其描述信息,存入内容之中

加载时机:

创建对象 创建子类对象 访问静态属性 调用静态方法 Class.forName(“全限定名”);

final

概念:最后的,不可更改的

final可修饰的内容:

(最终类)

方法(最终方法)

变量(最终变量)

final修饰类:此类不能被继承。

接口的语法:

接口相当于特殊的抽象类,定义的方式、组成部分与抽象类相似。

与抽象类的异同:

相同:

可编译成字节码文件。

不能创建对象。

可以做作为引用类型。

具备Object类中所定义的方法。

不同:

所有属性都是公开静态常量,隐式默认为:public static final 修饰

所有方法都是公开抽象方法,隐式默认为:public abstract 修饰

没有构造方法,公共代码块,静态代码块

什么是接口:

微观概念:接口是一种能力和约定。

接口的定义:代表了某种能力。

方法的定义:能力的具体要求。

抽象方法(规定子类必须存在的行为,规范了其行为的具体要求);

接口是一种能力,接口中的方法就是一种约定。

经验:JAVA为单继承,当父类的方法种类无法满足子类需求时,可实现接口扩充子类能力。

接口的规范:

任何类在实现接口时,必须实现接口中所有的抽象方法,否则此类为抽象类。

实现接口中的抽象方法时,访问修饰符必须是public.

接口引用:

同父类引用一样, 接口也可声明为引用,并指向实现类对象。

注意: 

仅可调用接口中所声明的方法,不可调用实现类中独有的方法。

可强制转回接口的实现类型,从而调用其原有的属性方法。


接口的多态:

接口引用,指向实例化接口对象,从而实现接口多态。

常见关系:

类与类:

单继承

extends:父类名称

类与接口:

多实现

implements 接口名称1,接口名称2,接口名称N

接口与接口:

多继承 extends

父类接口1,父类接口2,父类接口N

常量接口:

将多个常用于表示状态或固定值的变量,以静态常量的形式定义在接口统一管理,提高代码可读性。

枚举(规范了取值的类型):关键字 enumerate

enum state{

false,true,or

}

谁去Implements 那就是实现者

谁去new 实现类 那就是使用者

接口的回调:

接口回调:先有接口的使用者,后有接口的实现者

接口的好处

程序的耦合度降低

更自然的使用多态。

设计与实现完全分离。

更容易搭建程序框架。

更容易更换具体实现。

总结:

内部类的分类:

成员内部类、静态内部类、局部内部类、匿名内部类

概念:在一个类内部再定义一个完整的类。

class  Outer{

class Inner{

}

}

 

特点:

编译之后可以生成独立的字节码文件。

内部内可直接访问外部类的私有成员,而不破坏封装。

可谓外部类提供必要的内部功能组件。

成员内部类:

在类的内部定义,与实例变量、实例方法同级别的类。

外部类的一个实例部分,成员内部类依赖外部类对象的实现。

 

当外类、内部类存在重名属性时,会优先访问内部类属性。

成员内部类无法定义静态成员。

静态内部类:

不依赖外部类对象,可直接创建或通过类名访问,可声明静态成员。

 

局部内部类:

定义在外部类方法中,作用范围和创建对象范围仅限于当前方法。

局部内部类访问外部类当前方法中的局部变量时,因无法保障变量的生命周期与自身相同,变量必须修饰为final.

匿名内部类:

Object

getClass()方法

public final Class<?> getClass(){}

返回引用对象的实际类型

应用:通常用于判断两个引用中的实际存储对象类型是否一致

hashCode()方法

public int hashCode(){}

返回一个该对象的十进制的哈希码值

哈希算法根据对象的地址或字符串或数字计算出来的int类型的数值

哈希码并不是唯一,可保证相同对象返回相同的哈希码,尽量保证不同对象返回不同的哈希码。

toString()方法

public String toString(){}

返回该对象的字符串表现形式

可以根据程序需要覆盖该方法,如展示对象各个属性值。

equals()方法

public boolean queals(Object obj){}

默认实现为(this == obj) , 比较两个对象地址是否相同。

可进行覆盖,比较两个对象的内容是否相同。

equals() 方法的覆盖步骤:

public boolean equals(Student obj){

if(this == obj){

return false ;}

if(obj== null){

return false; }

if(this.getClass() != obj.getClass(){

return false}

if(this.name.equals(s.name) && this.age == s.age &&this.sex.equals(s.sex){

return true}

return false;

}

finalize()方法

当对象被判定为垃圾对象时,由JVM自动调用此方法,用以标记垃圾对象,进入回收队列。

垃圾对象:没有有效的引用指向此对象时,为垃圾对象。

垃圾回收:有GC销毁垃圾对象,释放数据存储空间。

自动回收机制:JVM的内存耗尽,一次性回收所有垃圾对象。

手动回收机制:使用System.gc();通知JVM执行垃圾回收。

可达性分析算法

包装类:

什么是包装类?

基本数据类型所对应的引用数据类型

Obect 可统一所有数据,包装类的默认值是null

包装类对应:

类型转换与装箱、拆箱

8种包装类提供不同类型间的转换方式:

Number父类中提供的6中共性方法;floatValuedoubleValuebyteValue....

parseXXX()静态方法;parseIntparseDouble....

valueOf()静态方法: intValueOfdoubleValueOf....

通过包装累继承得来的XXX ValueOf()方法,进行各类型之间的转换;

注意:需保证类型兼容(取值范围兼容、值类型兼容),否则抛出NumberFormatException异常


整数缓存区:

Java预先创建了256个常用的整数包装类型对象。

在实际应用当中,对已创建的对象进行复用。

String:

字符串为常量,创建之后不可改变

字符串字面存储在字符串中,可以共享

String s = “hello”; 产生一个对象,字符串池中存储。

String s = new String(“Hello”);  产生两个对象,池 与  堆 中各一个。

字符串实际是字符数组的包装类;

 

常用方法:

string.charAt(0)  通过下标获取字符串字符。

contains(String str): 判断当前字符串中是否包含str

toCharArray() : 将字符串转换成数组。

indexOf(String str fromIndex i): 查找str首次出现的下标,存在,返回下标值;不存在返回-1, 第二个参数为从下标i起始查询;

length() :返回串的长度;

trim() :去掉串前后的空格;

toUpperCase():将小写统一转为大写;

toLowerCase():将大写统一转为小写;

str1.equalsIgnoreCases(str2): 忽略大小写判断俩个串内容是否相同;

endsWith() :判断串是否已指定内容结尾;

startsWith() :判断串是否已指定内容开头;

replace():替换新内容;

Substring() :截取指定下标范围的内容;

StringBuffer:构造一个其中不带字符的字符串缓冲区,初始容量为16个字符,运行效率慢、线程安全。

线程安全的可变字符序列。一个类似于String的字符串缓冲区,但不能修改,虽然在任意时间点上他都包含某种特定的字符序列,但通过某些方法调用可以改变该序列的长度和内容。

StrintBuffer sb1 = new StringBuffer(“xxx”);

public String toString(); 返回串

StringBuilder:构造一个其中不带字符的字符串缓冲区,初始容量为16个字符,运行效率快、线程不安全。

一个可变的字符序列。此类提供一个与StringBuffer兼容的API,但不保证同步。该类被设计用作StringBuffer的一个简易替换,用在字符串缓冲区被单个线程使用的时候。建议优先采用该类,在多数情况下,StringBuilder更快。

StringBuilder sb2 = new StringBuilder(“xxx”);

StringBuilderStringBuffer所有API基本相同;只是运行效率不同。


BigDecimal 精确计算

不可变的,任意精度的有符号十进制数。

 

加:BigDecimal result = bg1.add(bg2);

减:BigDecimal result2 = bg1.subtract(bg2);

乘:BigDecimal result3 = bg1.multiply(bg2);

除:BigDecimal result4 = bg1.divide(bg2, 2,BigDecimal.ROUND_UP);

只有除法精确计算是需要添加保留位数,及取上或取下;

 

集合

概念:对象的容器,存储对象的对象,可代替数组。

特点:容器的工具类,定义了对多个对象进行操作的常用方法。

位置:java.util.*;

Collection体系集合:

 

特点:代表一组任意类型的对象,无序、无下标

Collection层次结构中的根接口,Collection表示一组对象,这些对象也可称为Collection的元素,一些collection允许有重复的元素,而另一些则不允许。

方法:

boolean add(Object obj) 添加一个对象

boolean addAll(Collection c)  讲一个集合中的所有对象添加到此集合中

void clear() 清空所有对象

boolean contains(Object o ) 检查此对象是否包含该对象

boolean equals(Obejct o) 比较此集合与指定对象是否相等

boolean isEmpty() 判断此结婚是否为空

boolean remove(Object o) 在此集合中移除o对象

int size() 返回此集合中的元素个数。

Object[] toArray() 将此集合转换为数组。

List 子接口

特点:有序、有下标、元素可重复

说明:有序的collection,此接口的用户可以对列表中每个元素的插入位置进行精确控制。用户可以根据元素的整数索引访问元素,并搜索列表中的元素。

set不同,列表通常允许元素重复

方法:

 

 

List 实现类:

ArrayList

数据结构实现,查询快、增删慢;

JDK1.2版本,运行效率快,线程不安全。

Vector(使用方法与ArrayList相同,目前暂不建议使用):   

数组结构实现,查询快、增删慢;

JDK1.0版本,运行效率慢、线程安全。

LinkedList:

链表结构实现,增删快,查询慢。

linklist接口的链接列表实现,实现所有可选的列表操作,并且允许元素(包括Null,除了实现List接口外,LinkedList类还未列表的开头及结尾getremoveinsert元素提供了统一的命名方法。这些操作允许将链接列表用作堆栈、队列或双端队列。

LinkedList 因是队列链式结构,开头与结尾的查询功能效率很高,所以添加了一些对应的方法

list.addFirst()list.addLast()list.peekFirst()list.peekLast()list.removeFirst()list.removeLast();

 

泛型集合:

概念:参数化类型、类型安全的集合,强制集合元素的类型必须一致。

特点:

编译时即可检查,而非运行时抛出异常。

访问时,不必类型转换(拆箱)。

不同泛型之间引用不能相互赋值,泛型不存在多态。


实例泛型:

如果是泛型类,在创建对象的时候指明泛型类型;

 

如果是泛型接口,在实现接口的是后指明泛型类型;

静态泛型:

 

 

Collections泛型集合

概念:集合工具类,定义了除了存取以外的集合常用方法。

方法:

public static void reverse(List<?> list) 反转集合中的元素顺序

public static void shuffle(List<?> list) 随机重置集合元素的顺序

public static void sort(List<?> list) 升序排序(元素类型必须实现Comparable接口)

Comparable<?> 排序接口  须实现其compareTo方法

Set 集合

特点:无序、无下标、元素不可重复

方法:全部继承自Collection的所有方法

Set的实现类:

HashSet【重点】:

基于HashCode实现元素不重复。

当存入元素的哈希码相同时。会调用equals进行确认,如结果为true,则拒绝后则的存入。

遍历HashSet的方法为foreach循环:

for遍历写法:

for(Student i : list)

System.out.println(i.age);

TreeSet:

基于排列顺序实现元素不重复。

实现了SortedSet接口,对集合元素自动排序。

元素对象的类型必须实现Comparable接口,指定排序顺序

通过CompareTo方法确定是否为重复元素。

使用TreeSet集合时,实现接口Comparable,之后针对性重写compareTo方法,否则排序去重不能达到理想效果。

@Override

public int compareTo(Teacher o) {

// TODO Auto-generated method stub

if(salary > o.salary ) {

return 1;

}else if(salary < o.salary ) {

return -1;

}else {

if(name.compareTo(o.name)>0) {

return 1;

}else if( name.compareTo(o.name)<0) {

return -1;

}else {

return 0;

}

}

}


Map体系集合

map接口的特点:

  1. 用于存储任意键值对(Key - Value
  2. 键:无序、无下标、不允许重复(唯一)
  3. 值:无序、无下标、允许重复

 

 

接口Map<K , V>

public interface Map<K , V>  : 将键映射到值的对象。一个映射不能包含重复的键;每个键最多只能映射到一个值。

特点:一对数据(KEY-Value),无序、无下标,键不可重复,值可重复。

方法:

V put(K key , V value) 将对象存入到集合中,关联简直。Key重复则覆盖原值。

Object get(Object key) 根据键值获取对应的值。

Set<K> keySet 返回所有Key内容的set集合。

Collection<V> values()  返回包含所有ValueCollection集合。

Set<Map.Entry<K,V>> entrySet() 键值匹配的Set集合

HashMap【重点】:线程不安全,运行效率快,允许用Null 作为Key 或者value

基于哈希标的Map接口的表现。此实现提供所有可选的映射操作,并与允许使用Null值和null键。(除了非同步和允许使用Null之外,HashMap类与Hashtable大致相同。)此类不保证映射的顺序,特别是它不保证该顺序恒久不变。

方法:listMap.containsKey(str)  查询map中是否有已存在的Key

HashTable:GDK1.0, 线程安全,运行效率慢,不允许使用null 作为key或者value;

Set<String> set = Country.countres.keySet(); 

Collection<String> values = Country.countres.values();

Set<Entry<String, String>> entry = Country.countres.entrySet();

for(Entry<String, String> i : entry)

System.out.println(i.getKey());

Properties: HashTable的子类,要求Keyvalue都是String.通常用于配置文件的读取。

Properties properties =  new Properties();

properties.setProperty("aaa", "bbbb");

properties.getProperty("aaa");

TreeMap:

实现了SortedMap接口(是MAP的子类),可以对Key自动排序。

Map<String, String> treeMap = new TreeMap<String, String>();

treeMap.put("CN1", "现在的年轻人");

该方法同样存在values() keySet() entrySet() 三个角度试图

 

总结:

异常

概念:程序在运行过程中出现的特殊情况。

异常处理的必要性:任何程序都可能存在未知问题、错误;如果不对这些问题进行正确处理,则可能导致程序的中端,造成不必要的损失。

Throwable:可抛出的,一切错误和异常的父类,位于java.lang包内。

Erro: JVM、硬件、执行逻辑错误,不能手动处理。

Exception: 程序在运行和配置中产生的问题,可处理。

RuntimeException:运行时异常,可处理,可不处理。

CheckedEception:受查异常,必须处理。

自动抛出异常:当程序在运行时遇到不符合规范的代码时。

手动抛出异常:语法  throw new 异常类型(“实际参数”;

产生异常结果:相当于遇到return语句,导致程序因异常而终止。

异常的传递:throws  声明异常,修饰符在方法参数列表后端。

受查异常:throws 声明异常,修饰在方法参数列表后端。

运行时异常:行时异常,可处理,可不处理.


try {

s1.setAge(12);

 (可能出现的异常代码)

} catch (Exception e) {

// TODO: handle exception

e.printStackTrace();  //打印堆栈中出错的内容

  (相关代码的自定义处理方案,如:getMessage()printStackTrace());

}finally{

(无论是否出现异常,都会执行finally里的语句)

}

自定义异常

需继承自ExceptionException的子类,常用的RuntimeException.

必要提供的构造方法:

无参数构造方法

String message 有参构造方法

方法覆盖:

带有异常声明的方法覆盖:

方法名、参数列表、返回值类型必须和父类相同。

子类的访问修饰符合父类相同或是比父类更宽。

子类中的方法,不能抛出比父类更多、更宽泛的异常。

总结:

 

 

  • List:有序集合,元素可重复
  • Set:不重复集合,LinkedHashSet按照插入排序,SortedSet可排序,HashSet无序
  • Map:键值对集合,存储键、值和之间的映射;Key无序,唯一;value 不要求有序,允许重复

Collections包下的unmodifiableXXX方法,通过这个方法返回的mapListSet,是不可以修改的

Collections.unmodifiableMap(Map)

Collections.unmodifiableList(List)
Collections.unmodifiableSet(Set)

public static void main(String[] args) {

List<Character> oldList = new ArrayList<Character>();

for (char i = 'A'; i < 'Z'; i++) {

oldList.add(i);

}

List<Character> unChangeList = Collections.unmodifiableList(oldList);

测试过后:调用addremove方法均会抛出错误java.lang.UnsupportedOperationException
线程

单词:  Runnable 可运行 就绪状态 可运行状态 就绪

什么是进程:

 

什么是线程:

 

线程的组成:

 

启用线程的方法:

方法1

class MyThread extends Thread{

@Override

public void run() {

for (int i = 0; i < 100; i++) {

System.out.println("线程1 "+Thread.currentThread().getId()+":"+i+"已开启");

}

}

}

MyThread myThread = new MyThread(null);

myThread.start();

方法2

class PrimeRun implements Runnable{

@Override

public void run() {

// TODO Auto-generated method stub

for (int i = 0; i < 100; i++) {

System.out.println("线程id: "+Thread.currentThread().getId()+"-"+i+"已开启");

}

}

}

PrimeRun primeRun = new PrimeRun();

PrimeRun p2 = new PrimeRun();

p2.start();

线程的状态(基本)

 

 

方法:

休眠: public static void sleep( long millis)  当前线程主动休眠 millis毫秒。

放弃:  public static void yield()  当前线程主动放弃时间片,会到就绪状态,竞争下一次时间片。

结合:  public final void join() 允许其他线程加入当前线程中,并优先执行。

线程的状态(等待):

 

线程的安全问题:

 

需求:A线程将“HELLO”存入数组的第一个空间;B线程将“World”存入数组的第一个空位。

线程不安全:

当多线程并发访问临界资源时,如果破坏原子操作,可能造成数据不一致。

临界资源:共享资源(同一个对象),一次仅允许一个线程使用,才可保证其正确性。

原子操作:不可分隔的多步操作,被视为一个整体,其顺序和步骤不可打乱或缺省。

同步方式(1

同步代码块:

synchronized临界资源对象{ //对离临界对象资源加锁

//代码块

}

注:

每个对象都有一个互斥锁标记,用来分配给线程的。

只有拥有对象互斥标记的线程,才能进入对该对象加锁的同步代码块。

线程退出同步代码块时,会释放相应的互斥锁标记。

 

线程的状态(阻塞)

 

 

同步的规则:

 


线程的通知:

等待:

public final void wait();

public final void wait(long timeout);

必须在堆obj加锁的同步代码块中。在一个线程中,调用obj.wait()时,此线程会释放拥有的所有锁标记。同时此线程处在无限期等待的状态中,释放锁,进入等待队列。

通知:

public final void notify();

public final void notifyAll();

必须在堆obj加锁的同步代码块中,从objWaiting中释放一个或全部线程。对自身没有任何影响。

经典问题:

 

关键字:synchronized  或者同步代码块 synchronized(){///}

总结:

 

守护线程:thread.setDaemon(true);守护线程拥有自动结束自己生命周期的特性,而非守护线程不具备这个特点

通常来说,守护线程经常被用来执行一些后台任务,但是呢,你又希望在程序退出时,或者说 JVM 退出时,线程能够自动关闭,此时,守护线程是你的首选。


Runtime.getRuntime().addShutdownHook(

new Thread(()-> System.out.println("The jvm exit Success!"))

);  //查看java虚拟机退出时机

Thread thread = new Thread(()->{//创建线程

while(true) { //不断执行

try {

Thread.sleep(1000);

System.out.println("I am running~~");

} catch (Exception e) {

e.printStackTrace();

// TODO: handle exception

}

}

}) ;

thread.setDaemon(true);//设置守护线程

thread.start();

try {

thread.sleep(2000);

} catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}finally {

System.out.println("main thread to exit!"); //打印主线程结束时机

}


线程池概念

现有问题:

线程是宝贵的内存资源、单个线程约1MB空间,过多分配易造成内存溢出。

频繁的创建及销毁线程会增加虚拟机回收效率、资源开销,造成程序性能下降。

线程池:

线程容器,可设定线程分配的数量上限。

将预先创建的线程对象存入池中,并重用线程池中的线程对象。

避免频繁的创建和销毁。

 

将任务提交给线程池,由线程池分配线程、运行任务,并在当前任务结束后复用线程。

获取线程池
常用的线程池接口和类(所在包 java.util.concurrent:

Executor:线程池的顶级接口。

ExecutorService:线程池接口,可通过submit(Runnable task) 提交任务代码。

Executors工厂类:通过此类可以获得一个线程池。

通过newFixedThreadPool(int nThreads) 获取固定数量的线程池。参数:指定线程池中线程的数量。

通过newCachedThreadPool() 获得动态数量的线程池,如不够则创建新的,没有上线。

ExecutorService serve = Executors.newFixedThreadPool(3);   //调用固定线程池

ExecutorService serve = Executors.newCachedThreadPool();   //调用缓存线程池

Runnable task = new MyTask();  //生成任务

erve.submit(task); //执行

 

 shutdown();结束所有线程。

   isTerminated(); 判断所有线程是否结束;

Callable接口

public interface Callable<V>{

public V call{} throws Exception;

}

JDK5加入,与Runnable接口类似,实现之后代表一个线程任务。

Callable具有泛型返回值、可以声明异常。

Future<V>接口

概念:异步接受ExecutorService.submit()所返回的状态结果,当中包含了call()的返回值。

V  代表futureget方法返回的结果类型,get方法以阻塞形式等待Future中的异步处理结果(call())

Future代表异步计算的结果,他提供了检查是否完成线程,及等待计算结果,并获取计算的结果。

 

接口实现:

class CallTask implements Callable <Integer>{

@Override

public Integer call() throws Exception {

int value = 1 ;

for(int i = 0 ; i < 10 ; i++ ) {

value += i;

System.out.println("task"+Thread.currentThread().getId()+": "+i);

};

return value;

}

}

调用:

ExecutorService serve = Executors.newCachedThreadPool();

Callable<Integer> task = new CallTask();

Future<Integer> result = serve.submit(task);  //返回Future类型结果;

result.get(); //获得返回的结果;

同步:

形容一次方法调用,同步一旦开始,调用者必须等待该方法返回,才能继续。

异步:

形容一次方法调用,异步一旦开始,像是一次消息传递,调用者告知之后立刻返回。二者竞争时间片,并发执行。

 

Lock接口

JDK5加入,与synchronized比较,显示定义,结构更灵活。

提供更多使用性方法,功能更强大、性能更优越。

常用方法:

void lock() //获取锁,如锁被占用,则等待。

boolean tryLock()   //尝试获取锁(成功返回true.失败返回false,不阻塞)

void unlock()   //释放锁

 

重入锁

ReentrantLock:Lock接口的实现类,与synchronized一样具有互斥锁功能。

 

读写锁

ReentrantReadWriteLock:

一种支持一写多读的同步锁,读写分离,可分别分配读锁、写锁。

支持多次分配读锁,使多个操作可以进行。

互斥规则:

-写:互斥,阻塞。

-写:互斥,读阻塞写、写阻塞读。

-读:不互斥、不阻塞。

在读操作远远高于写操作的环境中,可以保障线程安全的情况下,提高运行效率。

 

线程安全的集合

Collection集合体系下,除Vector 以外的线程安全集合。

 

Collections中的工具方法

Collections工具中提供了多个可以获得线程安全集合的方法。

 

JDK1.2提供,接口统一,维护性高,但性能没有提升,均已synchronized实现

CopyOnWriteArrayList

ArrsyList的一个线程安全辩题,其中所有可变操作(addset等等) 都是通过对底层数据进行一次新的复制来实现。

线程安全的ArrayList,加强版读写分离。

写有锁,读无锁,读与写之间不阻塞,优于读写锁。

写入时,先copy一个容器副本、在添加新元素,最后替换引用。

使用方法与ArrayList无异。

 

接口引用,更容易实现更换引用类   List list = new CopyOnWriteArrayList(); =>  List list = new ArrayList()  更换子类无差异。

CopyOnWriteArraySet

 

ConcurrentHashMap

初始容器默认为16段(Segment,使用分段锁设计。

不对整个Map加锁,而是为每个Segment加锁。

当多个对象存入同一个Segment时,才需要互斥。

最理想状态为16个对象分别存入16Setment,并行数量16.

使用方式与HashMap无异。

 

总结

 

线程池概念

 

获取线程池

 

 

CopyOnWriteArrayList

 

CopyOnWriteArraySet


Queue接口(队列)

Collection的子接口,表示队列FIFOFirst In First Out

 

ConcurrentLinkedQueue;

Queue的一个线程安全的队列。

线程安全、可高效率都城的队列,高并发下性能最好的队列。

无锁、CAS (compare and Swap)比较交换算法,修改的方法包含三个核心参数(V,E,N)   

V:要更新的变量、E:预期值、N:新值。

只有当V==EV=N;否则表示内容已经被更新过,则取消当前操作。

 

BlockingQueue接口(阻塞队列)

Queue的子接口,阻塞的队列,

阻塞队列

ArrayBlockingQueue:

数组结构实现,有界限列。(手工固定上线)

 

LinkedBlockingQueue:

链表结构实现,无界队列。(默认上线Integer.MAX_VALUE

 

总结:

什么是流

概念:内存与存储设备之间传输数据的通道。

 

流的分类

按方向【重点】:

输入流:将<存储设备>中的内容读入到<内存>中。

输出流:将<内存>中的内容读入到<存储设备>中。

 

按单位:

字节流:以字节为单位,可以读写所有数据。

字符流:吃字符为单位,只能读写文本数据。

按功能:

节点流:具有实际传输数据的读写功能。

过滤流:在节点流基础上增强功能。(装饰器、装饰类)

字节流:

过字节流的父类(抽象类):

InputStream:字节输入流;  此抽象类是表示字节输入流的所有类的超类。

 

OutputStream:字节输出流;  此抽象类是表示输出字节流的所有类的超类。

 

FileOutputStrean:

public void write(byte[] b )   一次写多个字节,将b数组中所有字节,写入输入流。

FileOutputStream output = new FileOutputStream("Files\test1.txt");

for (int i = 'a'; i < 'z'+1; i++) {

output.write(i);

}

byte[] bs = new byte[] {65,66,67,68,69,70};

output.write(bs,1,3);  

FileInputStream:

public int read(byte[] b  从流中读取多个字节,将读到内容存入b数组中,返回实际读到的字节数;如果达到文件的尾部,则返回-1;

FileInputStream input = new FileInputStream("Files\test1.txt"); // 创建输入流

byte[] cache = new byte[1024*256]; //设置缓存数组大小

for (int i = 0; ;) {  // 循环  或者 while true

int n = input.read(cache);  // 读取数据并缓存入cache

if(n == -1) {break;}; // 退出循环条件

for (int j = 0; j < n; j++) {  //打印读取到的数据

System.out.print((char)cache[j] + " ");

}

System.out.println();

}

字节过滤流:

缓冲流:BufferedOutputStream / BufferedInputStream

提高IO效率,减少访问磁盘的次数。

数据缓存在缓冲区,flush是讲缓存区的内容写入文件中,也可以直接close

 

OutputStream os = new FileOutputStream("Files\buffertest.txt"); //节点流

BufferedOutputStream bos = new BufferedOutputStream(os); //过滤流

bos.write('X');  //写入缓存之中

bos.flush();  //刷新缓冲(将缓冲中的数据,一次性写入文件中,并清空缓冲区)

bos.close();  // 级联执行flush()

BufferedInputStream 输入流的使用方法与建立数组缓存相同,且缓存大小默认为8192

InputStream fps = new FileInputStream("Files\buffertest.txt");

BufferedInputStream bis = new BufferedInputStream(fps);

while (true) {

int s = bis.read();

if(s == -1) {

break;

}

System.out.print((char)s+" ");

}

对象过滤流:

ObjectOutputStream / ObjectInputStream

 

使用流传输对象的过程称为序列化、反序列化。

 

因为String等常用类型 父类已实现接口 Serializable 所以可以直接使用序列化存储功能

当文件读取到尾部时,使用EOFException作为终止循环判断条件:

InputStream ips = new FileInputStream("Files\object.txt");

ObjectInputStream oiStream = new ObjectInputStream(ips);

while (true) {

try {

Student student = (Student) oiStream.readObject();

System.out.println(student.toString());

} catch (EOFException e) {

break;

}

}

字符编码

 

当编码方式和解码方式不一致时,会出现乱码

字符流

字符流的父类(抽象类):

Reader:字符输入流,用于读取字符流的抽象类。

Writer:字符输出流,写入字符流的抽象类。

FileWriter:

public void write(String str)  一次写多个字符,将b数组中所有字符,写入输出流。

Writer writer = new FileWriter("Files\writeIndex2.html");

writer.write(cache);

writer.close();

FileReader:

public int read(char[] c) 从流中读取多个字符,将读到的内容存入c数组,返回实际读到的字符数;如果达到文件的尾部,则返回-1

char[] cache = new char[1024*128];

Reader read = new FileReader("Files\index.html");

int n = 0;

while (true) {

n = read.read(cache);

if(n == -1) {break;};

}

字符过滤流

 

字符节点流

 

使用步骤:

创建节点流

[创建过滤流 设置字符编码集]

封装过滤流

读写数据

关闭流

 

 

总结:

 

File

概念:代表物理盘符中的一个文件夹或文件。

 

listFiles( fileFilter ) 方法:

该方法无参数时将返回所在文件目录下的所有文件,加入参数时,参数将实现接口 FileFilter,并覆盖方法accept(File file)

for (File string : dirFile.listFiles(new myFilter())) { System.out.println(string); }

class myFilter implements FileFilter{

@Override

public boolean accept(File file) { //自定义判断条件,通过返回true,不通过false;

if(file.isFile()&& file.getName().endsWith(".html")) {

return true;

}

return false;

}}

什么是网络

由点和线构成,表示诸多对象间的相互联系。

什么是计算机网络

为实现资源共享和信息传递,哦谈过通信线路连接起来的若干主机(Host

互联网:(Internet)点与点相连。

万维网:www world wide web 端与端的相连

物联网:IOT  internet of things 物与物相连

网络编程:让计算机与计算机之间建立连接、进行通信。

网络模型:

OSIoper system interconnection) 开放式系统互联

 

第一层:物理层为设备之间的数据通信提供传输信号和物理介质。(双绞线、光导纤维)。

第二层:链路层在物理层上,通过规程或协议(差错控制)来控制传输数据的正确性,MAC

第三层:网络层负责定义了能够表示所有网络节点的逻辑地址。(IP地址)

第四层:传输层负责是否选择差错恢复协议、数据流重用、错误顺序重排,(TCPUDP

第五层:会话层负责使用应用建立和维持会话,是通信在失效时继续恢复通信(断点续传)

第六层:表示层负责定义转换数据格式及加密,允许选择以二进制或ASCII 格式传输。

第七层:应用层负责文件访问和管理,可靠运输服务、远程操作服务。(HTTPFTPSMTP)

TCP/IP模型

一组用于实现网络互联的通信协议,将协议分成四个层次。

 

第一层:接口层负责建立电路连接,是整个网络的物理基础,点醒的洗衣包括以太网、ADSL等等。

第二层:网络层负责分配地址和传送二进制数据,主要协议是IP协议。

第三层:传输层负责传送文本数据,主要是协议是TCPUDP协议。

第四层:应用层负责传送各种最终形态的数据,是直接与用户打交道的层,典型协议是HTTPFTP等。

 

 

IP:

 

 


Port:

 

InetAddress

 

 

 

基于TCP的网络编程

Socket编程:

Socket(套接字)是网络中的一个通信节点。

分为客户端Socket与服务器ServerSocket.

通信要求:IP地址 + 端口号。

开发步骤:

 

类对象

类的对象:基于某个类 new出来的对象,也称为实例对象。

类对象:类加载的产物,封装了一个类的所有信息(类名、父类、接口、属性、方法、构造方法)

 


获取类对象

通过类的对象,获取类对象

Student s = new Student();

Class c = s.getClass();

通过类名获取类对象

Class c = 类名.class

通过静态方法获取类对象

Class c = Class.forName(“包名.类名”);

工厂设计模式

通开发中有一个非常重要的原则是“开闭原则”,对拓展开放、对修改关闭。

工厂模式主要负责对象创建的问题。

可通过反射进行工厂模式的设计,完成动态的对象创建。

使用反射创建类:

Class c = Teacher.class;

Teacher s2 = (Teacher)c.newInstance();

s2.name = "joba";

// 构造新对象

Teacher s4 = (Teacher)createObject("Teacher");

// 获得新对象的类型

Class<? extends Teacher> c4 = s4.getClass();

// 通过类型获得类方法

Method m = c4.getMethod("exam" , int.class);

// 执行有参方法,传入参数

Object result = m.invoke(s4 , 80);

// 打印返回的结果

System.out.println(result);

如果方法为私有方法  需使用

Method m = c4.getDeclaredMethod("calc", Double.class);

m.setAccessible(true);

m4.invoke(m, 100D);

单例模式

单例(Singleton: 只允许创建一个该类的对象。(天生线程安全)

创建单例对象所获得的对象为同一个:

1.饿汉式:天生线程安全、类加载创建(不好,不用的时候也被迫创建,占用一点点资源)

Singleton s = Singleton.getInstance();

System.out.println(s);  //singleton_16.Singleton@15db9742

Singleton s1 = Singleton.getInstance();

System.out.println(s1); //singleton_16.Singleton@15db9742

class Singleton{

private static final Singleton instance = new Singleton();

private Singleton() {};

public static Singleton getInstance() {

return instance;

}

}

2.懒汉式:使用时在创建、天生线程不安全(加锁)

class Singleton{

private static Singleton instance = null;

private Singleton(){}

public static Singleton getInstance() {

if(instance == null) {

instance = new Singleton();

}

return instance;

}

}

3.懒汉式:用时在创建、天生线程安全

class Singleton{

private Singleton(){}

private static class Holder{

static final Singleton instance = new Singleton();

}

public static Singleton getInstance() {

return Holder.instance;

}

}

总结:

 

原文地址:https://www.cnblogs.com/bomdeyada/p/14356566.html