java基础内容概括

Java语言三大平台

JavaSE: Java PlatForm Standrad Edtion

-- Java标准版

-- 适用于开发桌面型, C/S架构型的应用程序

-- C/S: Client/Server(客户端/服务器)

-- B/S: Browser/Server(浏览器/服务器)

JavaEE: Java PlatForm Enterprise Edtion

-- Java企业版(基于B/S架构的应用程序)

JavaME: Java PlatForm Micro Edtion

-- Java微型版(嵌入式手机应用开发)

Java特性:

1. 面向对象

2. 跨平台(一次编译到处运行)

3. 健壮性

4. 安全性(强类型语言取消指针)

跨平台实现:

1. 源代码

2. 将源代码(.java)编译成为字节码(.class)

3. 字节码文件运行在JVM(Java虚拟机)

5. 实现跨平台(一次编译到处运行), 是通过不同的系统所对应的JVM实现

Java核心机制:

1. JVM: Java虚拟机(Java Virtual Machine) 

2. GC: 垃圾回收器(Garbage Collection) 

GUI: 图形化用户接口

AWT

Swing

JVM:  Java虚拟机(Java Virtual Machine) 

-- 运行Java应用程序

JRE:  Java运行时环境(Java Runtime Envirment)

-- 提供Java的基础jar

-- 包含JVM

JDK: Java开发工具包(Java Development Kit)

-- 开发所需要的工具

-- 包含JRE

开发Java应用程序步骤:

1. 编写源代码

2. 将源代码编译成为字节码

-- javac

-- javac 源代码文件名.扩展名

3. 运行字节码

-- java

-- java 字节码文件

-- 注意:不能加文件扩展名

访问修饰符

public class HelloWorld{

public static void main(String[] args){

System.out.println("Hello World......");

}

}

public: 访问修饰符

class: 类修饰符

HelloWorld: 类名

-- 类名必须与文件名相同(大小写区分)

声明程序入口(格式固定)

public static void main(String[] args){

}

一个源代码文件中可以有多个class, 但只能有一个classpublic修饰

-- public修饰的class类名必须与文件名相同

Java语言严格区分大小写

Java语言中所有的符号均为半角符号

每条语句必须以分号结束

Java注释:

1. //: 单行注释

-- 将双斜杠后的内容不做任何处理

2. /* 注释内容 */ : 多行注释

-- 一般作用于对多行代码的注释

3. /** 注释内容 */ : 文档注释

-- 声明在类上或方法上

类名方法名参数名变量名...

-- 开发人员自行命名的东西

都称之为标识符

标识符命名规则:

1. 由字母、数字、特殊符号(下划线_、美元符号$)组成

2. 不能以数字开始

3. 长度无限制

4. 尽量使用英文单词命名

-- 拼音

5. 不能使用Java中的保留字与关键字

见名知意

常量: 在应用程序中不能被修改的值

常量命名: 全部大写, 多个单词之间使用下划线分隔

final int COUNT = 20;

使用关键字 final 表示常量

""表示字符串

字符串: 由多个字符组成的内容

"a"

''表示字符

字符: 由单个字符组成

'a'

"abc"

Java中的八种(四大类)基本数据类型:

1. 整型数值

1.1 字节: byte(在内存占用8位, 8bit

1.2 短整型: short(在内存中占用16位,2个字节)

1.3 整型: int(在内存中占用32位, 4个字节)

1.4 长整型: long(在内存中占用64位, 8个字节)

2. 浮点数值

2.1 单精度浮点值:float (在内存中占用32位, 4个字节)

2.2 双精度浮点值:double(在内存中占用64位, 8个字节)

3. 字符

3.1 字符: char(在内存中占用16位,2个字节)

4. 布尔

4.1 布尔:boolean(在内存中占用8位, 一个字节)

true, false

1 0

特殊类型: 引用类型/对象类型

数据类型转换:

  1. 自动升级

a) 在做运算过程中,级别低的数据类型自动升级为高级别的

b) byte, short, char在运算时自动升级成为int类型

c) byte->short/char->int->long->float->double

  1. 强制转换

a) 将高级别的数据类型强制转换成为低级别

b) 将运算之后产生的数据类型强制转换为指定的数据类型

c) 强制转换可能后造成数据精度丢失, 所以要小心使用

变量:

是一个可以在内存中保存数据的内存地址

在数据使用之前必须先向内存申请地址(声明变量)

在变量第一次使用之前必须先给变量赋值

相同的变量名称在作用域范围之内不允许重复声明定义, 但可以重新赋值

一次声明一个变量 :int  num;

一次声明一个变量并赋值: int num = 123;

一次声明多个变量: int n, m, I, k;

一次声明多个变量并赋值:int n = 1, m = 2, i = 3, k = 4;

按声明的位置:

  1. 局部变量

a) 有效范围只在当前所属的大括号之内

  1. 成员变量/成员属性/全局变量

a) 有效范围在当前的类中

类中包含:

  1. 成员属性
  2. 成员方法
  3. 构造方法
  4. 基本类型变量

按声明的数据类型划分:

a) 声明的数据类型为八种基本类型

  1. 引用类型变量/对象类型

a) 除基本类型之外的类型

程序执行过程:

  1. 将源代码编译成为字节码
  2. 将字节码加载至内存中
  3. 内存区域划分为

a) 方法区

  1. 类信息, 类变量(静态变量), 常量池

b) 堆栈区

  1. 保存的是局部变量
  2. 如果在引用变量, 则保存引用对象的内存地址值

c) 堆区

  1. 保存的是引用对象

运算符

+、-、*/%++--

++、后++: 对指定的值进行加1、减1的运算

++:先将变量的值加1之后再处理

++:先将变量进行处理之后再进行加1

逻辑运算符

&&:逻辑与

所有的表达式全部为true, 结果为true

如果有一个为false,结果为false

||:逻辑或

表达式中有一个结果为true, 结果为true

如果有一个表达式的结果为true, 那么后面所有的表达式将不会参与运算

!:取反

位运算(将数值转换为二进制进行运算)

~:按位取反

01, 遇10

&:按位与

有一个为0,结果为0

|:按位或

有一个为1, 结果为1

^:按位异或

相同为0, 不同为1

0000 0001  0000 0001 0000 0001

& 0000 0000     | 0000 0000    ^0000 0000

——————  ——————  ——————

0000 0000  0000 0001 0000 0001

位移运算

 有符号

<< : 左移, 低位补0

>>:右移, 高位被补符号位(之前符号位为00, 之前符号位为11

无符号

>>> 右移, 高位补0

表达式:

  1. 表达式运算之后的值需要与声明的变量的数据类型一致
  2. 运算符的优先级使用小括号提升即可

程序流程控制

  1. 顺序结构

a) 程序代码由上自下顺序执行

  1. 选择结构

a) 通过让指定的代码在满足指定条件的情况下执行

  1. if…else…
  2. switch…case…default
  3. 循环结构

a) 指定的代码被执行N次(N次由循环条件决定)

  1. for循环
  2. do…while循环
  3. while…循环

三种循环的区别

  1. do…while是先执行一次, 再判断条件
  2. while是先判断条件, 根据表达式的值决定是否执行
  3. for循环固定循环次数

a) 明确确定循环次数的确定下优先使用for

循环特殊控制:

  1. break: 跳出当前循环体
  2. continue:跳出当前循环, 继续下一次循环

 

 

进制之间的转换

十进制:逢101

二进制:逢21

八进制:逢81

十六进制:逢161 (0-9ABCDEF)

方法: 面向对象语言中的一种叫法

将能够实现某一种特定的功能的代码声明在某一段语句块之内,然后在需要实现该功能的地方调用

该语句块可以声明成为一个方法

-- 在一个类中方法不能够够重复声明

声明语法:

[访问控制修饰符] [静态修饰符] [常量修饰符返回类型 方法名称(参数列表){

方法体实现代码

}

返回类型: 每个方法必须指定相应的返回类型(数据类型)

-- 返回值使用关键字 return指定

-- 如果方法没有返回值, 必须声明为void

参数列表语法:数据类型 参数名称[,数据类型参数名2…]

方法调用:

在需要实现指定方法的功能时, 直接调用即可

调用方式:

  1. 在本类中调用

a) 直接指定方法名并且给定相应的参数即可

  1. 在不同类中调用

a) 需要使用类名.方法名([参数值列表])

  1. 如果被调用的方法为非静态方法

a) 对象名.方法名([参数值列表))

参数:

  1. 实参: 调用方法时给定的实际值
  2. 形参:在方法声明时指定的参数

程序代码是顺序执行, 如果在代码中调用了指定的方法, 则先执行该方法中的代码, 方法中的代码执行完毕之后, 返回至原调用的地方, 再按顺序向下执行其它代码

方法参数:

  1. 参数长度/参数个数必须相同
  2. 参数的数据类型必须一一对应
  3. 形参与实参的名称可以不同

返回类型

  1. 方法无返回时必须声明 void
  2. 如果有返回值, 方法声明中必须指定对应的返回数据类型, 而且方法最后必须使用return返回一个具体的值
  3. 方法声明的返回类型必须与return 的数据类型一致
  4. 接收返回值的数据类型必须方法声明的返回类型一致
  5. 如果方法没有声明返回的具体数据类型(声明为void), 方法体中可以使用return关键字,但return表示结束当前方法的运行,直接返回至调用的地方

a) 需要注意reutrn 关键字的逻辑问题导致编译无法通过

方法的重载(overload

在一个类中可以重复定义同名的方法

  1. 方法重载必须在同一个类中
  2. 参数个数不能同
  3. 如果参数个数相同, 参数的数据类型不同

a) 在调用方法时,优先匹配数据类型相同的方法

  1. 如果参数个数相同, 且数据类型相同, 参数声明的顺序不能相同
  2. 方法声明的返回类型不影响重载

数组:

作用: 一个变量中可以保存多个值所有值的数据类型必须相同

数组的数据类型属于对象类型/引用类型

-- 引用变量保存在栈中的是一个指向堆内存的引用地址

声明语法:

数据类型[] 数组名称;

int[] arr; ―― Java规范

//int arr[]; 不建议使用此方式

数组初始化方式:

  1. 静态初始化:在声明数组时进行初始化赋值

a) int[] array = {10, 20, 30};

b) 声明并且赋值之后, 数组长度也就确定

  1. 动态初始化:在使用前进行初始化赋值

a) int[] array = new int[数组长度];

b) int[] array = new int[5];

c) array[0] = 12; array[1] = 23; array[4] = 123;

访问数组元素的方式

通过元素对应的索引/下标来访问

第一元素对应的索引值为0

array[索引值]  ->  array[0]

array[1], array[2]

数组对象提供了一个length的属性, 方便获取该数组的长度

―― 获取元素个数

―― 数组中最后一个元素的下标数组长度减一

数组长度一旦确定, 不能修改

可变参数:

方法的参数个数是未知的, 但数据类型必须确定

语法:

数据类型… 参数名称

public void test(int… params){

方法体代码;

}

可变参数按照数组的方式去处理

注: 可变参数必须声明在参数列表的最后

冒泡排序(Bubble Sort)

v 原理:将相邻的两个元素进行比较, 如果不等,则进行交换

顺序查找从第一个元素开始顺序比较查找

二分查找又称折半查找. 从已排序的数组中进行查找

– 首先确定该查找区间的中间点位置: int mid = (low+upper) / 2; 

– 然后将待查找的值与中间点位置的值比较:

– 若相等,则查找成功并返回此位置。

– 若中间点位置值大于待查值,则新的查找区间是中间点位置的左(或右)边区域。

– 若中间点位置值小于待查值,则新的查找区间是中间点位置的右(或左)边区域。下一次查找是针对新的查找区间进行的。

二维数组

一维数组中嵌套一维数组

语法 

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

数据类型[][] 数组名 = new int[行数][]

数据类型[][] 数组名 = new int[行数][列数]

初始化:

  1. 静态初始化

a) 数据类型[][] 数组名 = {{12, 3}, {2, 3, 4}, {3, 45}}

b) 数据类型[][] 数组名 = new数据类型[][]{{1, 2, 3}, {2, 3, 4}, {3, 4,5}};

  1. 动态初始化

堆栈

保存局部变量的值相对于引用变量保存的是内存地址

保存的是对象的所有成员属性的值

方法区类的信息

数据区静态变量的值与常量值及字符中常量值

静态方法:

本类中调用直接使用方法名(参数列表)

非本类中调用类名.方法名(参数列表)

-- 也可以以 对象名.方法名(参数列表的方式被调用

非静态方法:

本类中调用直接使用方法名(参数列表)

非本类中调用对象名.方法名(参数列表)

在静态方法中不能直接访问非静态成员(成员属性/成员方法)

在非静态方法中可以直接调用静态成员

方法参数传递:

  1. 以值的方式传递
  2. 以引用的方式传递

Java中参数传递是以值的方式时行 传递

在被调用的方法中如果修改参数(形参)不会影响调用之前的实参的值

在传递的过程中将实参的值复制一份交给形参

-- 形参是实参的一个副本

基本数据类型传递的是实际的值

引用类型传递的是对象的引用地址

面向对象的三大特征

  1. 封装
  2. 继承
  3. 多态

封装将类中的成员隐藏起来对外部不可见(外部不可以直接访问)

-- 关键字: private 私有的

可以修饰成员属性成员方法构造器

不能将类修饰成为private

private修饰的成员只能在本类中访问在其它类中不能访问

将成员属性声明为private, 然后提供对应的公共的(public)get/set方法以方便获取/修改其值

-- 将类中所有的成员属性修饰为private

-- 类中所有的成员方法修饰为public 

Person p = new Person();

它在内存中做了哪些事情?

答案:

:将 Person.class  文件加载到内存中。

:在堆内存中创建一个对象 Person 

:把 Person  中的属性进行默认初始化。

:把 Person  中的属性进行显示初始化。

:调用构造代码块如果没有,不执行这个操作

:调用构造函数进行初始化。

:在栈内存中声明 Person  类型的变量 

:把堆内存的地址引用赋给了栈内存中 

抽象类

具体类对现实世界的具体事物进行描述

抽象类对现实世界中的某一种事物进行描述

-- 所有事物都有共同的行为但实现方式不同

-- 在抽象类中对行为不进行实现而是由具体子类去实现该行为

-- 抽象类中可以包含抽象方法也可以包含成员方法

使用关键字 abstract 声明抽象类

抽象类中可以有抽象方法

-- 没有方法体

-- 抽象方法必须使用abstract 关键字修饰

public abstract void eat();

具体子类继承抽象类之后必须实现(重写/覆盖)抽象父类中的抽象方法

或将该子类声明成为抽象类

抽象类不能被实例化

抽象类中的构造方法是为了给成员属性赋值

如果一个类中有抽象方法,那么该类必须声明为抽象类

接口:

具体类对现实世界的具体事物进行描述

抽象类对现实世界中的某一种事物进行描述

接口: 对现实世界中的不同事物进行描述

-- 不同事物的共同行为(抽象方法)

接口使用关键字interface实现

接口中可以包含:

  1. 静态常量

a) 接口定义的成员属性默认为静态常量

  1. 抽象方法

a) 在接口只能定义抽象方法

b) 声明的方法默认就是抽象方法

接口所有成员默认的访问控制修饰符为 public 

接口不能被实例化

接口不能被子类继承只能由子类实现

- 使用关键字 implements 

实现子类必须重写/覆盖接口中的所有抽象方法,如果没有全部实现该实现子类必须声明成为抽象类

接口可以继承接口且可以继承多个父接口

多个类可以实现同一个接口

一个类可以实现多个不同的接口

final

可以修饰:

  1. 变量

a) 被final修饰的变量称之为常量值不能被改变

  1. 显式赋值
  2. 动态代码块中赋值
  3. 构造器赋值
  4. 如果声明为静态常量那么赋值方式:
    1. 显式赋值
    2. 静态代码块赋值
    3. 方法

a) 被final修饰的方法称之最终方法不能被子类重写/覆盖

a) 被final修饰的类称之为最终类不能被继承

多态:

  1. 本态对象的本类类型

Teacher t = new Teacher();

本态引用对象引用类型为本类类型(声明的数据类型为本类类型)

  1. 多态对象的父类类型

Person p = new Teacher();

多态引用父类的引用指向子类的实例对象

-- 运行时使用子类类型

                -- 编译时使用父类类型

多态参数:

由多态产生的问题:

由于编译时使用父类类型进行编译也就是无法调用子类中独有的方法

在实际开发中,使用多态参数的方式来解决此访问

方法接收一个父类类型的参数

 

内部类:

内部类中能否访问外部类的成员

内部类可以直接访问外部类的成员

外部类中否访问内部类的成员

外部类必须通过内部类的实例对象访问内部类的成员

内部类怎么实例化对象

  1. 外部类名.内部类名 内部类对象名 = new外部类名().new内部类名();
  2. 外部类名 外部类对象名 = new外部类名();

外部类名.内部类名 内部类对象名 外部类对象名. new内部类名();

静态内部类:

静态内部类中能否访问外部类的成员

只能直接访问外部类的静态成员

如果要访问外部类的非静态成员,必须以外部类的实例对象的方式调用

外部类中否访问静态内部类的成员

不能直接访问静态内部类的成员

也不能以静态类名.方法名的方式调用

只能以静态内部类的对象方式调用

静态内部类怎么实例化对象

外部类名.内部类名 内部类对象名 = new外部类名.内部类名();

方法中的内部类

能否访问外部类成员

可以直接访问外部类的成员

外部类能否直接访问方法中的内部类成员

不能

方法中的内部的有效范围只在所属方法体中

异常

异常在应用程序运行期间产生错误而进行通知的一种机制

一旦出现异常应用程序会因意外而中止运行

异常中包含:

  1. 异常的原因
  2. 异常的信息(错误信息)
  3. 异常的位置

异常是以堆栈的方式抛出

异常分类 :

  1. 运行时异常应用程序在编译时可以通过但在运行时可能会抛出异常

a) 非受检异常

b) 在应用程序运行时,由用户输入了错误的信息而造成

c) 由RuntimeException对象及Error对象

  1. 非运行时异常在编译期间由编译器做出检查

a) 受检异常

b) Exception对象

  • RuntimeException

– ArithmeticException:数学计算异常

– NullPointerException:空指针异常

– NegativeArraySizeException:负数组长度异常

– ArrayIndexOutOfBoundsException:数组索引越界异常

– ClassNotFoundException:类文件未找到异常

– ClassCastException:造型异常

  • IOException

– FileNotFoundException:文件未找到异常

– EOFException:读写文件尾异常

– MalformedURLException:URL格式错误异常

– SocketException:Socket异常

– IOException

处理异常的方式

  1. 捕获
  2. 抛出
  3. 捕获再抛出

捕获:

try{

必须是可能抛出异常的代码

}catch(异常类名 对象名){

捕获异常后的处理

}

异常处理:

  1. 打印异常的错误信息

a) 异常对象名.getMessage();

  1. 打印异常的堆栈信息

a) 异常对象名.printStackTrace();

catch语句块中声明的异常类必须与代码产生的异常对象是同一类型

-- 可以是产生的异常对象的本类类型或父类类型

finally语句块中会执行关闭相关连接或释放资源的操作

如果语句块中的return, 那么finally语句块会在return 前执行

抛出

在代码中产生异常应用程序直接抛出一个异常对象

使用关键字throwthrows声明抛出

throw: 代码级抛出

-- 开发人员可以自行决定在哪行代码抛出异常

-- 实例化异常对象时可以指定异常的错误信息

-- 使用throw 抛出的异常如果为运行时异常那么调用的地方无需捕获

如果抛出的异常如果为非运行时异常那么调用的地方必须捕获

且必须使用throws声明抛出

-- throw == return

throws: 方法级抛出

-- 一般声明抛出的是非运行时异常(受检异常)

-- 如果throws声明抛出的是运行时异常(非受检异常), 调用的地方无需捕获

-- 如果throws声明抛出的是非运行时异常(受检异常), 调用的地方必须捕获

使用throws可以直接声明抛出异常无需使用throw关键字

-- 声明多个异常多个异常之间使用逗号分隔

捕获抛出

先将产生的异常对象声明为一个新的异常对象对这个新的异常对象进行抛出处理

自定义异常:

自定义类必须继承一个异常类

  1. RuntimeException: 将自定义异常类声明为一个运行时异常类
  2. Exception: 将自定义异常类声明为一个非运行时异常类

声明重载构造器

String是一个不可变的字符序列

String类是final类型不能被继承

常用方法:

concat(str): 字符串连接

replace(oldChar, newChar): 以指定的新内容替换字符串中指定的旧的内容

substring(startIndex): 从指定的索引开始,截取字符串至结尾

substring(startIndex, endIndex): 返回从指定的索引开始至指定的结束索引之间的内容(结束索引处的字符不包含在内)

toLowerCase(): 将指定的字符串内容全部转换为小写

toUpperCase(): 将指定的字符串内容全部转换为大写

trim(): 去掉字符串首尾的空格及制表符

toCharArray(): 将指定的字符串转换成为字符数组

endWith(str): 当前字符串是否以指定的内容结束

startWith(str) : 当前字符串是否以指定的内容开始

indexOf(char)

indexOf(int)

indexOf(String): 返回指定字符串第一个字符的索引位置

indexOf(String str, int startIndex)

正向查找(从前向后)

从当前字符串中查询指定内容第一次出现的索引位置

如果未找到返回-1

lastIndexOf(int )

lastIndexOf(char )

lastIndexOf(String )

lastIndexOf(String str, int startIndex)

反向查找(从后向前)

equals(str): 当前字符串与指定的字符串进行比较是否相等

equalsIgnoreCase(str): 当前字符串与指定的字符串进行比较忽略大小写

compareTo(str):

charAt(index): 获取指定索引处的字符

length(): 是一个方法获取当前字符串的长度

数组长度是一个属性

split(str): 以指定的内容对当前字符串进行分隔返回字符串数组

集合Java提供的一系列类的实例

-- 一系列类组成了集合框架(Collection系列)

集合作用:

用来存储多个元素

与数组的区别:

可以看作是一个可变长度的数组

可以存储不同类型的对象

集合元素必须是对象类型,不能是基本类型

数组长度一旦确定不能更改

数组元素必须是同一种类型的对象

数组既可以是基本数据类型也可以是对象类型

Collection

List

ArrayList

LinkedList

Vector

Set

HashSet

SortedSet

TreeSet

Map

HashMap

Hashtable

SortedMap

TreeMap

List: 有序且可重复

有序添加元素的顺序

可重复相等的两个元素可以添加至同一集合中

Set: 无序且不可重复

无序依次获取元素时不按添加顺序

不可重复相等的元素不能添加到同一集合中

Map: 映射集合

Key-Value

Collection常用API

– int size(); 返回此collection中的元素数。

– boolean isEmpty(); 判断此collection中是否包含元素。

– boolean add(Object element); 向此collection中添加元素。

– boolean addAll(Collection c);将指定collection中的所有元素添加到此collection中

– boolean contains(Object obj); 判断此collection是否包含指定的元素。

– boolean containsAll(Collection c); 判断此collection是否包含指定collection中的所有元素。

– boolean remove(Object element); 从此collection中移除指定的元素。

– boolean removeAll(Collection c); 移除此collection中那些也包含在指定collection中的所有元素。

– void clear(); 移除collection中所有的元素。

– boolean retainAll(Collection c); 仅保留此collection与c的交集元素,其他删除,此方法与removeAll()正好相反。

– Iterator iterator(); 返回在此collection的元素上进行迭代的迭代器。

– Object[] toArray(); 把此collection转成数组。

List:

ArrayList: 使用数组结构保存元素

  1. 根据索引查找元素速度快
  2. 添加/删除效率较低(涉及数组中大量元素的移动)
  3. 是非线程安全的

LinkedList: 使用链表结构保存元素

  1. 查询元素效率较低
  2. 添加/删除效率较高(不会涉及元素的大量移动)
  3. 是非线程安全的

Vector: 使用数组结构保存元素

  1. 是线程安全的
  2. 查询/添加/删除效率都较低

List常用API

  • public Object get(int index) 
    • 返回列表中的元素数
    • public Object add(int index, Object element);  
      • 在列表的指定位置插入指定元素.将当前处于该位置的元素(如果有的话)和所有后续元素向右移动
      • public Object set(int index, Object element) ; 
        • 用指定元素替换列表中指定位置的元素
        • public Object remove(int index)      
          • 移除列表中指定位置的元素
          • public ListIterator listIterator()      
            • 返回此列表元素的列表迭代器

Set集合:

Set: 无序且不可重复

HashSet: 使用的是Hash算法实现

是基于HashMap映射集合实现的

Set集合中添加元素时,执行方式如下:

  1. 调用hashCode()方法比较两个对象的hash如果hash值不同直接将元素添加到Set集合中如果hash值相同那么执行第二步
  2. 调用equals(obj)方法如果比较结果为false, 那么将元素添加到Set集合中,如果比较结果为true, 不会添加

在实体类中需要重写hashCode()equals(Object obj)两个方法

-- 确定该类的实例对象需要保存到Set集合中时

SortedSet

TreeSet 是有序按照自然排序的规则进行排序

二叉树

Map集合是映射集合

key-Value键值对的形式保存数据

key必须在集合中是唯一的不能重复

一个key对应一个value

如果要新增的keyvaluemap中已存在新增的key会被丢弃,value会覆盖之前的vlaue

Map:

HashMap

SortedMap

TreeMap

Hashtable

Map<Key, Value> map = new HashMap<Key, Value>();

Map<Integer, String> map = new HashMap<Integer, String >();

常用API:

put(key, value) 向当前集合中添加元素

get(key): 根据指定的key从集合中查找对应的value

keySet(): 返回当前集合中的包含所有keySet集合

entrySet(): 返回当前集合中的所有的keyvalueSet集合

HashMap: 

keyvalue允许为null

非线程安全的

Hashtable

keyvalue都不允许为null

线程安全的

File: 对应系统中的某一个文件

public class TestFile {

public static void main(String[] args) {

File file = new File("d:/share/test.txt");

boolean flag = file.exists();

System.out.println(file + " 是否存在: " + flag);

// 没有物理文件的文件对象不能读写

System.out.println("是否能读: " + file.canRead());

System.out.println("是否能写: " + file.canWrite());

File f = new File("src/com/io/test/TestFile.java");

// 有物理文件的文件对象能进行读写操作

System.out.println("是否能读: " + f.canRead());

System.out.println("是否能写: " + f.canWrite());

System.out.println("是否存在: " + f.exists());

System.out.println("文件名: " + f.getName());

System.out.println("文件绝对路径: " + f.getAbsolutePath());

System.out.println("文件相对路径: " + f.getPath());

System.out.println("文件上级父路径: " + f.getParent());

long time = f.lastModified();

System.out.println("最后修改时间: " + time);

Date date = new Date(time);

// yyyy-MM-dd hh:mm:ss

DateFormat df = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");

String str = df.format(date);

System.out.println(str);

System.out.println("文件长度: " + f.length());

System.out.println("是否文件夹: " + f.isDirectory());

System.out.println("是否文件: " + f.isFile());

System.out.println("是否为隐藏文件: " + f.isHidden());

File fd = new File("d:/share/day01");

flag = fd.isDirectory();

System.out.println("fd.isDirectory = " + flag);

String[] strs = fd.list();

for(String s : strs){

System.out.println(s);

}

File[] files = fd.listFiles();

for(File f2 : files){

if(f2.isDirectory()){

// 是目录

}

// 非目录

}

File f3 = new File("test");

// mkdir(), createNewFile()

if(!f3.exists()){

flag = f3.mkdir();

System.out.println("test目录创建成功: " + flag);

}

File f4 = new File("test/test.txt");

try {

if(!f4.exists()){

flag = f4.createNewFile();

System.out.println("test/test.txt创建成功: " + flag);

}

catch (IOException e) {

e.printStackTrace();

}

File f5 = new File("test/te/ts/t");

/*if(!f5.exists()){

flag = f5.mkdir();

System.out.println("t目录创建成功: " + flag);

}*/

if(!f5.exists()){

flag = f5.mkdirs();

System.out.println("t目录创建成功: " + flag);

}

}

}

I/O

Input: 输入流 => 读取/接收数据

Output: 输出流 => 写入/发送数据

流分类:

1按数据流动方向分:

输入流

输出流

按数据量(数据类型):

字节流一次传输8(1个字节)

Stream结尾

字符流一次传输16(2个字节)

Reader/Writer结尾

: InputStreamReader/OutputStreamWriter是转换流

InputStreamReader: 将字节流转换成为字符流

OutputStreamWriter: 将字符流转换成为字节流

按对数据的处理功能分:

基本流/节点流

包装流/处理流扩展了更加强大的处理功能处理数据更为方便

InputStream

是所有输入流的父类

read() // 读取一个字节

read(byte[])

read(byte[] b, int offset, int len)

close()

OutputStream

是所有输出流的父类

write(int)

write(byte[])

write(byte[] b, int offset, int len)

flush();

close();

节点流 基本流

处理流 包装流

BufferedInputStream

bufferedOutputStream

缓冲字节流

BufferedReader

readLine()

BufferedWriter

缓冲字符流

文件读写开发步骤:

  1. 创建流对象
  2. :输入流/输出流

a) 如果文件为二进制文件使用字节流

b) 如果文件为普通文件使用字符流

  1. 关闭流

一、java中多线程的执行:抢占式执行

二、创建线程的方式

1、继承Thread

(1)创建线程类继承Thread并覆盖run()方法

(2)在主线程中创建线程类的对象

(3)调用线程对象的start()方法启动线程

2、实现Runnable接口

(1)创建线程类实现Runnble接口并实现run()方法

(2)main方法中创建线程类的实例

(3)使用第2步创建的实例创建Thread对象

(4)调用start()方法启动线程

3、线程的状态

三、线程的状态

1、创建:创建Thread对象

2、创建-可运行:调用start()方法

3、可运行-正在运行:抢占到CPU资源

4、正在运行-可运行:CPU资源被其他线程抢走

5、正在运行-结束:run()方法执行结束

四、线程中常用的方法

1、获取当前的线程Thread对象:Thread.currentThread()

2、获取线程对象的名字:getName()

3、当前线程的是否活动:isAlive()

4、当前线程的状态:getState()

5、设置线程的名称:setName()

6、线程睡眠:sleep(long n)

(1)使线程暂停执行n毫秒

(2)当前程睡眠时,就不再参与抢占CPU资源,提供其他线程优先执行的机会

(3)唤醒睡眠线程

a.主动唤醒:时间到了

b.被动唤醒:调用interrupt()方法,抛出InterruptedException异常信号唤醒线程

(4)线程从运行状态变为阻塞状态,该状态不能抢占CPU资源

7、线程暂停执行:yield()

(1)线程从运行状态变为可运行状态(就绪状态)

(2)当该线程回到了可运行状态后,仍然可以与其他线程抢占CPU资源执行。

8、调用的线程先执行,其他线程阻塞:join()

(1)暂停的线程从运行变为阻塞状态,就不再参与抢占CPU资源

(2)唤醒阻塞的线程

a.结束唤醒:优先执行的线程结束

b.主动唤醒:时间到了

c.被动唤醒:调用interrupt()方法,抛出InterruptedException异常信号

反射

通过反射机制可以实现获取类中的字段方法并且调用

可以创建已知类名字符串的实例对象

类的类名字符串:

类的全名包括类所在的包名

猜你喜欢

转载自www.cnblogs.com/LDYOnTheWay/p/9256764.html