一、基本语法
1.1 关键字
定义:被Java语言赋予了特殊含义,用做专门用途的字符串(单词)
特点:关键字中所有字母都为小写
用于定义数据类型的关键字
class 、interface 、enum、byte、short、int、long、float、double、char、boolean、void
用于定义数据类型值的关键字
true、false、null
用于定义流程控制的关键字
if else switch case default while do for break continue return
用于定义访问权限修饰符的关键字
private、protected、public
用于定义类,函数,变量修饰符的关键字
abstract、final、static、synchronized
用于定义类与类之间关系的关键字
extends、implements
用于定义建立实例及引用实例,判断实例的关键字
new 、this、super、instanceof
用于异常处理的关键字
try、catch、finally、throw、throws
用于包的关键字
package 、import
其他修饰符关键字
native、strictfp、transient、volatile、assert
1.2 标识符
标识符:
Java 对各种变量、方法和类等要素命名时使用的字符序列称为标识符
凡是自己可以起名字的地方都叫标识符。
定义合法标识符规则:
由26个英文字母大小写,0-9 ,_或 $ 组成
数字不可以开头。
不可以使用关键字和保留字,但能包含关键字和保留字。
Java中严格区分大小写,长度无限制。
标识符不能包含空格。
注意:在起名字时,为了提高阅读性,要尽量有意义,“见名知意”。
Java中的名称命名规范:
包名:多单词组成时所有字母都小写:xxxyyyzzz
类名、接口名:多单词组成时,所有单词的首字母大写:XxxYyyZzz
变量名、方法名:多单词组成时,第一个单词首字母小写,第二个单词开始每个单词首字母大写:xxxYyyZzz
常量名:所有字母都大写。多单词时每个单词用下划线连接:XXX_YYY_ZZZ
1.3 变 量
- 1.3.1、变量的概念:
内存中的一个存储区域
该区域有自己的名称(变量名)和类型(数据类型)
Java中每个变量必须先声明,后使用
该区域的数据可以在同一类型范围内不断变化
使用变量注意:
变量的作用域:一对{ }之间有效
初始化值
定义变量的格式:数据类型 变量名 = 初始化值
变量是通过使用变量名来访问这块区域的
-
1.3.2、变量的分类
对于每一种数据都定义了明确的具体数据类型,在内存中分配了不同大小的内存空间。
- 按数据类型
变量分基本数据类型(byte,short,int,long,float,double,char,boolean)
引用数据类型(类class,接口interface,数组)两种。
- 按声明的位置的不同
在方法体外,类体内声明的变量称为成员变量。
在方法体内部声明的变量称为局部变量。
变量分成员变量和局部变量两种。
成员变量:【实例变量(不以static修饰)和类变量(以static修饰)】
局部变量:【形参(方法签名中定义的变量)和方法局部变量(在方法内定义)和代码块局部变量(在代码块内定义)】
注意:二者在初始化值方面的异同:
同:都有生命周期
异:局部变量除形参外,需显式初始化
- 1.3.3、整数类型:byte、short、int、long
Java各整数类型有固定的表数范围和字段长度,不受具体OS的影响,以保证java程序的可移植性。
java的整型常量默认为 int 型,声明long型常量须后加‘l’或‘L’
byte (1字节=8bit)
short(2字节)
int (4字节)
long (8字节)
-
1.3.3、浮点类型:float、double
与整数类型类似,Java 浮点类型也有固定的表数范围和字段长度,不受具体OS的影响。 Java 的浮点型常量默认为double型,声明float型常量,须后加‘f’或‘F’。 浮点型常量有两种表示形式: 十进制数形式:如:5.12 512.0f .512 (必须有小数点) 科学计数法形式:如:5.12e2 512E2 100E-2 float (4字节) double(8字节)
-
1.3.4、字符类型:char
char 型数据用来表示通常意义上“字符”(2字节) 字符型常量的三种表现形式: 字符常量是用单引号(‘ ’)括起来的单个字符,涵盖世界上所有书面语的字符。例如:char c1 = 'a'; char c2 = '中'; char c3 = '9'; Java中还允许使用转义字符‘\’来将其后的字符转变为特殊字符型常量。例如:char c3 = ‘\n’; // '\n'表示换行符 直接使用 Unicode 值来表示字符型常量:‘\uXXXX’。其中,XXXX代表一个十六进制整数。如:\u000a 表示 \n。 char类型是可以进行运算的。因为它都对应有Unicode码。
1.3.5、布尔类型:boolean boolean 类型适于逻辑运算,一般用于程序流程控制: if条件控制语句; while循环控制语句; do-while循环控制语句; for循环控制语句; boolean类型数据只允许取值true和false,无null。 不可以0或非 0 的整数替代false和true,这点和C语言不同。
-
1.3.6、基本数据类型转换
自动类型转换:容量小的类型自动转换为容量大的数据类型。数据类型按容量大小排序为: char —> | |->int ->long ->float ->double byte —>short —>| 有多种类型的数据混合运算时,系统首先自动将所有数据转换成容量最大的那种数据类型,然后再进行计算。 byte,short,char之间不会相互转换,他们三者在计算时首先转换为int类型。 当把任何基本类型的值和字符串值进行连接运算时(+),基本类型的值将自动转化为字符串类型。
1.4运算符
运算符是一种特殊的符号,用以表示数据的运算、赋值和比较等。
算术运算符
赋值运算符
比较运算符(关系运算符)
逻辑运算符
位运算符
三元运算符
- 1.4.1、算术运算符
算符 运算 范例 结果
+ 正号 +3 3
- 负号 b=4; -b -4
+ 加 5+5 10
- 减 6-4 2
* 乘 3*4 12
/ 除 5/5 1
% 取模 7%5 2
++ 自增(前):先运算后取值 a=2;b=++a; a=3;b=3
++ 自增(后):先取值后运算 a=2;b=a++; a=3;b=2
-- 自减(前):先运算后取值 a=2;b=--a a=1;b=1
-- 自减(后):先取值后运算 a=2;b=a-- a=1;b=2
+ 字符串相加 “He”+”llo” “Hello”
算术运算符的注意问题
如果对负数取模,可以把模数负号忽略不记,如:5%-2=1。 但被模数是负数则不可忽略。此外,取模运算的结果不一定总是整数。
对于除号“/”,它的整数除和小数除是有区别的:整数之间做除法时,只保留整数部分而舍弃小数部分。
例如:int x=3510;x=x/1000*1000; x的结果是?
“+”除字符串相加功能外,还能把非字符串转换成字符串.例如:System.out.println("5+5="+5+5); //打印结果是?
以下二者的区别:
System.out.println('*' + '\t' +'*');
System.out.println("*" + '\t' +'*');
-
1.4.2、赋值运算符
符号:= 当“=”两侧数据类型不一致时,可以使用自动类型转换或使用强制类型转换原则进行处理。 支持连续赋值。 扩展赋值运算符: +=, -=, *=, /=, %=
1.4.3、比较运算符
运算符 运算 范例 结果
== 相等于 4==3 false
!= 不等于 4!=3 true
< 小于 4<3 false
> 大于 4>3 true
<= 小于等于 4<=3 false
>= 大于等于 4>=3 true
instanceof 检查是否是类的对象 “Hello” instanceof String true
比较运算符的结果都是boolean型,也就是要么是true,要么是false。
比较运算符“==”不能误写成“=” 。
-
1.4.4、逻辑运算符
&—逻辑与 | —逻辑或 !—逻辑非 && —短路与 || —短路或 ^ —逻辑异或
a b a&b a|b !a a^b a&&b a||b
true true true true false false true true
true false false true false true false true
false true false true true true false true
false false false false true false false false
逻辑运算符用于连接布尔型表达式,在Java中不可以写成3<x<6,应该写成x>3 & x<6 。
“&”和“&&”的区别:
单&时,左边无论真假,右边都进行运算;
双&时,如果左边为真,右边参与运算,如果左边为假,那么右边不参与运算。
“|”和“||”的区别同理,||表示:当左边为真,右边不参与运算。
异或( ^ )与或( | )的不同之处是:当左右都为true时,结果为false。
理解:异或,追求的是“异”!
-
1.4.5、位运算符
运算符 运算 范例 << 左移 3 << 2 = 12 --> 3*2*2=12 >> 右移 3 >> 1 = 1 --> 3/2=1 >>> 无符号右移 3 >>> 1 = 1 --> 3/2=1 & 与运算 6 & 3 = 2 | 或运算 6 | 3 = 7 ^ 异或运算 6 ^ 3 = 5 ~ 反码 ~6 = -7 位运算是直接对二进制进行运算 << 空位补0,被移除的高位丢弃,空缺位补0。 >> 被移位的二进制最高位是0,右移后,空缺位补0;最高位是1,空缺位补1。 >>> 被移位二进制最高位无论是0或者是1,空缺位都用0补。 & 二进制位进行&运算,只有1&1时结果是1,否则是0; | 二进制位进行 | 运算,只有0 | 0时结果是0,否则是1; ^ 相同二进制位进行 ^ 运算,结果是0;1^1=0 , 0^0=0不相同二进制位 ^ 运算结果是1。1^0=1 , 0^1=1 ~ 正数取反,各二进制码按补码各位取反负数取反,各二进制码按补码各位取反
-
1.4.6、三元运算符
格式: (条件表达式)? 表达式1:表达式2; | | | |——> 为true,运算后的结果是表达式1; |——> 为false,运算后的结果是表达式2; 表达式1和表达式2为同种类型 三元运算符与if-else的联系与区别: 1)三元运算符可简化if-else语句 2)三元运算符要求必须返回一个结果。 3)if后的代码块可有多个语句
1.5 程序流程控制
-
顺序结构
- 程序从上到下逐行地执行,中间没有任何判断和跳转。
-
分支结构
根据条件,选择性地执行某段代码。
有if…else和switch两种分支语句
-
if语句三种格式:
1. if(true){ 执行代码块; } 2. if(条件表达式){执行代码块; } else{ 执行代码块; } 3. if(条件表达式){ 执行代码块; } else if (条件表达式){ 执行代码块; } …… else{ 执行代码块; }
-
switch和if语句的对比
if和switch语句很像,具体什么场景下,应用哪个语句呢? 如果判断的具体数值不多,而且符合byte、 short 、int、 char这四种类型。虽然两个语句都可以使用,建议使用swtich语句。因为效率稍高。 其他情况:对区间判断,对结果为boolean类型判断,使用if,if的使用范围更广
-
循环结构
根据循环条件,重复性的执行某段代码。 有while、do…while、for三种循环语句。 注:JDK1.5提供了for each循环,方便的遍历集合、数组元素。
-
循环语句功能
在某些条件满足的情况下,反复执行特定代码的功能
-
循环语句的四个组成部分
初始化部分(init_statement) 循环条件部分(test_exp) 循环体部分(body_statement) 迭代部分(alter_statement)
-
循环语句分类
for 循环 while 循环 do/while 循环
-
1.6 数组
数组是多个相同类型数据的组合,实现对这些数据的统一管理
数组中的元素可以是任何数据类型,包括基本数据类型和引用数据类型
数组属引用类型,数组型数据是对象(object),数组中的每个元素相当于该对象的成员变量
- 一维数组
-
声明方式:
type var[] 或 type[] var 例如: int a[]; int[] a1; double b[]; Mydate[] c; //对象数组 Java语言中声明数组时不能指定其长度(数组中元素的数), 例如: int a[5]; //非法
-
一维数组初始化
动态初始化:数组声明且为数组元素分配空间与赋值的操作分开进行
int[] arr = new int[3]; arr[0] = 3; arr[1] = 9; arr[2] = 8; MyDate dates[]; dates = new MyDate[3]; dates[0] = new MyDate(22, 7, 1964); dates[1] = new MyDate(1, 1, 2000); dates[2] = new MyDate(22, 12, 1964);
静态初始化:在定义数组的同时就为数组元素分配空间并赋值。
int a[] = new int[]{ 3, 9, 8}; int[] a = {3,9,8}; MyDate dates[] = { new MyDate(22, 7, 1964), new MyDate(1, 1, 2000), new MyDate(22, 12, 1964) }
-
数组元素的默认初始化
数组是引用类型,它的元素相当于类的成员变量,因此数组一经分配空间,其中的每个元素也被按照成员变量同样的方式被隐式初始化。例如: public class Test { public static void main(String argv[]){ int a[]= new int[5]; System.out.println(a[3]); //a[3]的默认值为0 } }
对于基本数据类型而言,默认初始化值各有不同
对于引用数据类型而言,默认初始化值为null(注意与0不同!) 数组元素的引用
-
定义并用运算符new为之分配空间后,才可以引用数组中的每个元素;
数组元素的引用方式:数组名[数组元素下标]
数组元素下标可以是整型常量或整型表达式。如a[3] , b[i] , c[6*i];
数组元素下标从0开始;长度为n的数组合法下标取值范围: 0 —>n-1;如int a[]=new int[3]; 可引用的数组元素为a[0]、a[1]、a[2]
每个数组都有一个属性length指明它的长度,例如:a.length 指明数组a的长度(元素个数)
数组一旦初始化,其长度是不可变的
- 多维数组
-
二维数组[][]:数组中的数组
格式1(动态初始化):int[][] arr = new int[3][2];
定义了名称为arr的二维数组 二维数组中有3个一维数组 每一个一维数组中有2个元素 一维数组的名称分别为arr[0], arr[1], arr[2] 给第一个一维数组1脚标位赋值为78写法是:arr[0][1] = 78;
格式2(动态初始化):int[][] arr = new int[3][];
二维数组中有3个一维数组。 每个一维数组都是默认初始化值null (注意:区别于格式1) 可以对这个三个一维数组分别进行初始化 arr[0] = new int[3]; arr[1] = new int[1]; arr[2] = new int[2]; 注: int[][]arr = new int[][3]; //非法
格式3(静态初始化):int[][] arr = new int[][]{{3,8,2},{2,7},{9,0,1,6}};
定义一个名称为arr的二维数组,二维数组中有三个一维数组 每一个一维数组中具体元素也都已初始化 第一个一维数组 arr[0] = {3,8,2}; 第二个一维数组 arr[1] = {2,7}; 第三个一维数组 arr[2] = {9,0,1,6}; 第三个一维数组的长度表示方式:arr[2].length; 注意特殊写法情况:int[] x,y[]; x是一维数组,y是二维数组。 Java中多维数组不必都是规则矩阵形式
-
四种访问权限修饰符
Java权限修饰符public、protected、private置于类的成员定义前,用来限定对象对该类成员的访问权限。
修饰符 类内部 同一个包 子类 任何地方
private Yes
default(缺省) Yes Yes
protected Yes Yes Yes
public Yes Yes Yes Yes
对于class的权限修饰只可以用public和default(缺省)。
public类可以在任意地方被访问。
default类只可以被同一个包内部的类访问。
二、面向对象编程
-
java类及类的成员
类是有属性和方法构成 属 性:对应类中的成员变量 行 为:对应类中的成员方法
-
类的语法格式
修饰符 class 类名 {
属性声明;
方法声明;
}说明:修饰符public:类可以被任意访问
类的正文要用{ }括起来举例: public class Person{ private int age ; //声明私有变量 age public void showAge(int i) { //声明方法showAge( ) age = i; } }
Field = 属性 = 成员变量,Method = (成员)方法 = 函数
public class Person { String name; // 属性 int age; boolean isMarried; // 成员变量 // 构造方法 public Person() { } // 方法或函数 public void walk() { System.out.println("人走路。。。。"); } //代码块 { name = "张三"; age = 17; isMarried = false; } // 方法或函数 public String display() { return "人的名字是:" + name + ",年龄是:" + age + ",Married:" + isMarried; } //内部类 class pet{ String name; float weight; } }
-
主函数:
public static void main(String[] args){};
是一个特殊的函数。作为程序的入口,可以被jvm调用。
主函数的定义:
public:代表着该函数访问权限是最大的。
static:代表主函数随着类的加载就已经存在了。
void:主函数没有具体的返回值。
main:不是关键字,但是是一个特殊的单词,可以被jvm识别。
(String[] arr):函数的参数,参数类型是一个数组,该数组中的元素是字符串。字符串类型的是数组。
主函数是固定格式的:jvm识别。
jvm在调用主函数时,传入的是new String[0];
类、对象、属性、方法
类:类似于生活中的“类别”,是对事物抽象的描述。
对象:是类具体的存在。
属性:绝大部分在生活中是使用“名词”来描述的,可以使用值量化的
方法:在生活中表现为“动词”的,是由一系列的行为构成的,是对行为模式的描述
public class Person {
String name;
int height;
float weight;
int gender;
void run() {}
void eat() {}
void sleep() {}
}
成员变量与局部变量
成员变量也称实例变量
成员变量作用于整个类中,存在堆内存中
局部变量作用于函数中,或者语句中,存在栈内存中
四个关键字(this,super,static,final )
-
this
作用:用于区分局部变量和成员变量同名情况 this代表它所在属函数的对象引用 简单说:哪个对象在调有this所在函数,this就代表哪个对象 this的应用: 当定义类中功能时,该函数内部要用该函数的对象时,这时用this来表示这个对象但凡本类功能内部使用了本类对象,都用this表示 this语句用于构造函数之间互相调用 this语句只能定义在构造函数的第一行
-
super
supper的使用和this的使用几乎一致。 注意:super语句一定定在子类构造函数的第一行
-
static
static关键字用于修饰成员(成员变量和成员函数) 被修饰后的成员具备以下特点: 1.随着类的加载而加载 也就是说:静态会随着类的消失而消失。说明它的生命周期最长。 2.优先于对象存在 静态是先存在的,对象是后存在的 实例变量和类变量(被静态修饰的成员变量)的区别: a.存放位置: 类变量随着类的加载而存在于方法区中, 实例变量随着对象建立而存在于堆内存中。 b.生命周期: 类变量生命周期最长,随着类的消失而消失 实例变量生命周期随着对象的消失而消失 3.被所有对象所共存 4.可以直接被类名调用 静态有利有弊 1.利处:对对象的共享数据进行单独的储存,节省空间,没有必要每个对象都存储一份可以直接被类名调用 弊端:生命周期过长 访问出现局限性(静态虽好,但只能访问静态的) 使用注意事项 1.静态方法只能访问静态成员 非静态方法既可以访问静态也可以访问非静态 2.静态方法中不可以写this,super关键字 3.主函数是静态的 用法:是一个修饰符,用于修饰成员(成员变量,成员函数)。 当成员被静态修饰后,就多了一个调用方式,除了可以被对象调用外,还可以直接被类名调用。'类名.静态成员'。 class Person{ String name;//成员变量(实例变量) static String country="CN";//静态的成员变量(类变量) } 什么时候使用静态? 从两方面下手: 因为静态修饰的内容有成员变量和函数。 什么时候定义静态变量(类变量)呢? 1.当对象中出现共享数据时,该数据被静态所修饰 2.对象中的特有数据要定义成非静态存在于堆内存中 什么时候定义静态函数? 1.当功能内部没有访问到非静态数据(对象的特有数据),那么该功能可以定义成静态的。 静态的应用: 每一个应用程序中都有共性的功能,可以将这些功能进行抽取,独立封装以便复用。
-
final
final可以修饰类,方法,变量。 final修饰的类不可以被继承成 final修饰的方法不可以被复写 final修饰的变量是一个常量。只能赋值一次,既可以是修饰成员变量,又可以修饰局部变量 final int x=3; 当描述事物时,一些数据的出现是固定的,那么这时为了增强阅读性,都给这些值起个名字,便于阅读 而这个值不需要改变,所以加上final修饰。作为常量:书写规范所有字母大写,如果由多个单词组成。 单词之间通过_连接,例如:final int MAX_VALUE=99999; 内部类只能访问被final修饰的局部变量
面向对象三大特性(封装,继承,多态)
-
1.封装
是指隐藏对象的属性和实现细节,仅对外提供公共访问方式 好处:将变化隔离 便于使用 提高重要性 提高安全性 封装原则: 将不需要对外提供的内容都隐藏起来 把属性都隐藏,提供公共方式对其访问 private:私有,权限修饰符:用于修饰类中的成员(成员变量,成员函数)只在本类中有效 注意:私有仅仅是封装的一种表现形式
-
2.继承
通过�extends�关键字让类与类之间产生继承关系。 多个类中存在相同属性和行为时,将这些内容抽取到单独一个类中,那么多个类无需再定义这些属性和行为,只要继承那个类即可。 多个类可以称为子类,单独这个类称为父类或者超类。 作用:代码重用、代码复用 父类代码在子类中不用重复编写 单继承: 一个子类只能有一个父类 一个父类可以有多个子类
-
3.多态:
多种形态,在编译期和运行期是不同的形态,在需要父类的对象时候,可以使用子类的对象,在需要抽象的对象时候,可以使用具现的对象。 Java源程序需要经过编译后才可以运行,表现为需要使用javac.exe指令对源程序进行编译,将会把源程序(*.java)编译为字节码文件(*.class),并使用java.exe指令运行程序 public class Demo { public static void main(String[] args) { int x = 6; int y = 10 + 3; int z = x + y; InputStream in = new FileInputStream("xxx"); } } 多态的应用:数组多态、参数多态、返回值多态
两大抽象(抽象类和接口)
-
1.抽象类
Java中可以定义没有方法体的方法,该方法的具体实现由子类完成,该方法称为抽象方法,包含抽象方法的类就是抽象类。 抽象类的特点: 抽象类和抽象方法必须用abstract关键字来修饰。 抽象方法只有方法声明,没有方法体,定义在抽象类中。 格式:修饰符abstract返回值类型函数名(参数列表); 抽象类不可以被实例化,也就是不可以用new创建对象。 抽象类和一般类的区别: 相同点:抽象类和一般类都是用来描述事物的,都在内部定义了成员。 不同点: 1.一般类有足够的信息描述事物。 抽象类描述事物的信息有可能不足。 2.一般类中不能定义抽象方法,只能定义非抽象方法。 抽象类中可定义抽象方法,同时也可以定义非抽象方法。 3.一般类可以被实例化。 抽象类不可以被实例化。
-
2.接口
定义:当一个抽象类中的方法都是抽象的时候,这时可以将该抽象类用另一种形式定义和表示,就是接口 作用:结构设计工具,用来解耦合 是一个极端的抽象类 用interface 代替class 用implements 代替 extends 接口中,只能定义: 公共的常量 公共的抽象方法 公共的内部类或内部接口 一个类可以实现多个接口 class A implements B,C,D{ } class A extends S implements B,C,D{ } 抽象类与接口的异同点 相同点: 都是不断向上抽取而来的。 不同点: 1.抽象类需要被继承,而且只能单继承。 接口需要被实现,而且可以多实现。 2.抽象类中可以定义抽象方法和非抽象方法,子类继承后,可以直接使用非抽象方法。 接口中只能定义抽象方法,必须由子类去实现。 3.抽象类的继承,是is a关系,定义该体系的基本共性内容。 接口的实现是like a关系。
重载(Overload)与重写(Override)
-
1.Overload
重载是在同一个类中,允许存在若干个同名方法的机制。 重载的多个方法必须有不相同的参数列表,表现为:参数的数据类型、数量、顺序不同。 判断是否允许重载,无视返回值类型。 构造方法也是方法,所以,构造方法也可以重载。
-
2.Override
重写是在类与类之间实现继承关系以后,在子类中编写父类中已经声明的方法。 当子类重写在父类中已经声明的方法时,不可以使用比父类声明时使用的更严格的访问权限。 例如父类方法使用的权限是protected,则子类重写时可以继续使用protected,也可以使用public,但不可以使用private。
四个内部类
成员内部类
静态(成员)内部类
局部内部类
匿名内部类
-
1.成员内部类
类的声明与外部类的其它成员(属性、方法……)在外部类的结构上是同等级别的。 例如: public class OutterClass { private int i; public void test() { InnerClass ic = new InnerClass(); } private class InnerClass { } } 由于成员内部类是外部类的一部分,所以,在没有创建出外部类的对象之前,不可以创建内部类的对象。 由于成员内部类是外部类的“成员”,所以,可以使用任何访问权限修饰符进行修饰。
-
2.静态(成员)内部类:
使用了static进行修饰的成员内部类。 public class OutterClass { private int i; public void test() {} private static class InnerClass { } } 由于静态成员可以直接加载到内存,所以,可以在不创建外部类的对象时,直接创建静态内部类的对象。 由于静态内部类使用了static修饰符,则在静态内部类中,无法直接访问外部类的非静态成员。
-
3.局部内部类:
在方法中编写的内部类。例如: public class OutterClass { public void test() { int i = 100; class InnerClass { public int x; public void run() {} } } } 局部内部类不可以使用任何修饰符(public、private、static……),因为这些修饰符是用于修饰类的成员的。 由于局部内部类是声明在方法中的,而方法中的代码区分先后顺序,所以,使用局部内部类,必须在声明局部内部类之后,且,该局部内部类只能作用于所在的方法。 局部内部类不可以直接访问局部变量,如果一定要访问该量,需要将变量修饰为final,或者提升为全局变量。
-
4.匿名内部类:
直接new出已知的类的子类对象,或者接口的抽象类对象,例如: public class MainActivity extends Activity { private View.OnClickListener listener = new View.OnClickListener { public void onClick(View view) { } }; protected void onCreate(Bundle bundle) { new View.OnClickListener() { public void onClick(View view) { } }; } } 由于匿名内部类是直接创建出对象的,如果是直接在方法中创建对象,则该匿名内部类符合局部内部类的特征,例如不可以直接访问局部变量等等; 内部类可以访问外部类的所有成员,无论这些成员是使用什么样的权限修饰的。
异常
是什么?是对问题的描述。将问题进行对象的封装。
异常体系:
Throwable
|--Error
|--Exception
|--RuntimeException
异常体系的特点:异常体系中的所有类以及建立的对象都具备可抛性。
也就是说可以被throw和throws关键字所操作。
只有异常体系具备这个特点。
-
throw和throws的用法:
throw定义在函数内,用于抛出异常对象。 throws定义在函数上,用于抛出异常类,可以抛出多个用逗号隔开。 当函数内容有throw抛出异常对象,并未进行try处理。必须要在函数上声明,都在编译失败。 注意,RuntimeException除外。也就说,函数内如果抛出的RuntimeExcpetion异常,函数上可以不用声明。
如果函数声明了异常,调用者需要进行处理。处理方法可以throws可以try。
-
异常有两种:
编译时被检测异常 该异常在编译时,如果没有处理(没有抛也没有try),编译失败。 该异常被标识,代表这可以被处理。 运行时异常(编译时不检测) 在编译时,不需要处理,编译器不检查。 该异常的发生,建议不处理,让程序停止。需要对代码进行修正。
-
异常处理语句:
try { 需要被检测的代码; } catch () { 处理异常的代码; } finally { 一定会执行的代码; }
-
有三个结合格式:
1. try { } catch () { } 2. try { } finally { } 3. try { } catch () { } finally { }
注意:
1,finally中定义的通常是 关闭资源代码。因为资源必须释放。
2,finally只有一种情况不会执行。当执行到System.exit(0);fianlly不会执行。
-
自定义异常:
定义类继承Exception或者RuntimeException 1,为了让该自定义类具备可抛性。 2,让该类具备操作异常的共性方法。 当要定义自定义异常的信息时,可以使用父类已经定义好的功能。 异常异常信息传递给父类的构造函数。 class MyException extends Exception { MyException(String message) { super(message); } }
自定义异常:按照java的面向对象思想,将程序中出现的特有问题进行封装。
-
异常的好处:
1,将问题进行封装。 2,将正常流程代码和问题处理代码相分离,方便于阅读。
-
异常的处理原则:
1,处理方式有两种:try 或者 throws。 2,调用到抛出异常的功能时,抛出几个,就处理几个。 一个try对应多个catch。 3,多个catch,父类的catch放到最下面。 4,catch内,需要定义针对性的处理方式。不要简单的定义printStackTrace,输出语句。 也不要不写。 当捕获到的异常,本功能处理不了时,可以继续在catch中抛出。 try { throw new AException(); } catch (AException e) { throw e; } 如果该异常处理不了,但并不属于该功能出现的异常。 可以将异常转换后,在抛出和该功能相关的异常。 或者异常可以处理,当需要将异常产生的和本功能相关的问题提供出去, 当调用者知道。并处理。也可以将捕获异常处理后,转换新的异常。 try { throw new AException(); } catch (AException e) { // 对AException处理。 throw new BException(); } 比如,汇款的例子。
-
异常的注意事项:
在子父类覆盖时: 1,子类抛出的异常必须是父类的异常的子类或者子集。 2,如果父类或者接口没有异常抛出时,子类覆盖出现异常,只能try不能抛。
线程
进程:是一个正在执行中的程序。
每一个进程执行都有一个执行顺序。该顺序是一个执行路径,或者叫一个控制单元。-
线程:就是进程中的一个独立的控制单元。
线程在控制着进程的执行。一个进程中至少有一个线程。 Java VM 启动的时候会有一个进程java.exe. 该进程中至少一个线程负责java程序的执行。 而且这个线程运行的代码存在于main方法中。 该线程称之为主线程。 扩展:其实更细节说明jvm,jvm启动不止一个线程,还有负责垃圾回收机制的线程。
-
线程的状态。
1,被创建。 2,运行。 3,冻结。 4,消亡。
-
如何在自定义的代码中,自定义一个线程呢?
通过对api的查找,java已经提供了对线程这类事物的描述。就Thread类。
-
创建线程的第一种方式:继承Thread类。
步骤: 1,定义类继承Thread。 2,复写Thread类中的run方法。 目的:将自定义代码存储在run方法。让线程运行。 3,调用线程的start方法, 该方法两个作用:启动线程,调用run方法。 发现运行结果每一次都不同。 因为多个线程都获取cpu的执行权。cpu执行到谁,谁就运行。 明确一点,在某一个时刻,只能有一个程序在运行。(多核除外) cpu在做着快速的切换,以达到看上去是同时运行的效果。 我们可以形象把多线程的运行行为在互相抢夺cpu的执行权。 这就是多线程的一个特性:随机性。谁抢到谁执行,至于执行多长,cpu说的算。
-
为什么要覆盖run方法呢?
Thread类用于描述线程。
该类就定义了一个功能,用于存储线程要运行的代码。该存储功能就是run方法。
也就是说Thread类中的run方法,用于存储线程要运行的代码。 -
创建线程的第二种方式:实现Runable接口
步骤: 1,定义类实现Runnable接口 2,覆盖Runnable接口中的run方法。 将线程要运行的代码存放在该run方法中。 3,通过Thread类建立线程对象。 4,将Runnable接口的子类对象作为实际参数传递给Thread类的构造函数。 为什么要将Runnable接口的子类对象传递给Thread的构造函数。 因为,自定义的run方法所属的对象是Runnable接口的子类对象。 所以要让线程去指定指定对象的run方法。就必须明确该run方法所属对象。 5,调用Thread类的start方法开启线程并调用Runnable接口子类的run方法。
-
实现方式和继承方式有什么区别呢?
实现方式好处:避免了单继承的局限性。 在定义线程时,建立使用实现方式。
-
两种方式区别:
继承Thread:线程代码存放Thread子类run方法中。 实现Runnable,线程代码存在接口的子类的run方法。
-
-
多线程的运行出现了安全问题。
问题的原因: 当多条语句在操作同一个线程共享数据时,一个线程对多条语句只执行了一部分,还没有执行完, 另一个线程参与进来执行。导致共享数据的错误。 解决办法: 对多条操作共享数据的语句,只能让一个线程都执行完。在执行过程中,其他线程不可以参与执行。
-
Java对于多线程的安全问题提供了专业的解决方式。
就是同步代码块。 synchronized(对象) { 需要被同步的代码 } 对象如同锁。持有锁的线程可以在同步中执行。 没有持有锁的线程即使获取cpu的执行权,也进不去,因为没有获取锁。 火车上的卫生间---经典。 同步的前提: 1,必须要有两个或者两个以上的线程。 2,必须是多个线程使用同一个锁。 必须保证同步中只能有一个线程在运行。
好处:解决了多线程的安全问题。
弊端:多个线程需要判断锁,较为消耗资源,
-
如果同步函数被静态修饰后,使用的锁是什么呢?
通过验证,发现不在是this。因为静态方法中也不可以定义this。 静态进内存是,内存中没有本类对象,但是一定有该类对应的字节码文件对象。 类名.class 该对象的类型是Class 静态的同步方法,使用的锁是该方法所在类的字节码文件对象。 类名.class
Java中的ApI
String类
字符串是一个特殊的对象
字符串是一个常量
字符串一旦初始化就不可改变
没有子类
String s1 ="abc";
String s2 =new String("abc")
String s3 ="abc";
System.out.println(s1==s2); //false
System.out.println(s1==s3); //true
System.out.println(s1.equals(s2)); //true 判断字符串是否相同
//s1和s2有什么区别?
//s1在内存中有一个对象
//s2在内存中有两个对象
-
字符串常见的操作
常见的操作有哪些? "abcd" 1,获取。 1.1 字符串中的包含的字符数,也就是字符串的长度。 int length():获取长度。 1.2 根据位置获取位置上某个字符。 char charAt(int index): 1.3 根据字符获取该字符在字符串中位置。 int indexOf(int ch):返回的是ch在字符串中第一次出现的位置。 int indexOf(int ch, int fromIndex) :从fromIndex指定位置开始,获取ch在字符串中出现的位置。 int indexOf(String str):返回的是str在字符串中第一次出现的位置。 int indexOf(String str, int fromIndex) :从fromIndex指定位置开始,获取str在字符串中出现的位置。 int lastIndexOf(int ch) : 2,判断。 2.1 字符串中是否包含某一个子串。 boolean contains(str): 特殊之处:indexOf(str):可以索引str第一次出现位置,如果返回-1.表示该str不在字符串中存在。 所以,也可以用于对指定判断是否包含。 if(str.indexOf("aa")!=-1) 而且该方法即可以判断,有可以获取出现的位置。 2.2 字符中是否有内容。 boolean isEmpty(): 原理就是判断长度是否为0. 2.3 字符串是否是以指定内容开头。 boolean startsWith(str); 2.4 字符串是否是以指定内容结尾。 boolean endsWith(str); 2.5 判断字符串内容是否相同。复写了Object类中的equals方法。 boolean equals(str); 2.6 判断内容是否相同,并忽略大小写。 boolean equalsIgnoreCase(); 3,转换。 3.1 将字符数组转成字符串。 构造函数:String(char[]) String(char[],offset,count):将字符数组中的一部分转成字符串。 静态方法: static String copyValueOf(char[]); static String copyValueOf(char[] data, int offset, int count) static String valueOf(char[]): 3.2 将字符串转成字符数组。** char[] toCharArray(): 3.3 将字节数组转成字符串。 String(byte[]) String(byte[],offset,count):将字节数组中的一部分转成字符串。 3.4 将字符串转成字节数组。 byte[] getBytes(): 3.5 将基本数据类型转成字符串。 static String valueOf(int) static String valueOf(double) //3+"";//String.valueOf(3); 特殊:字符串和字节数组在转换过程中,是可以指定编码表的。 4,替换 String replace(oldchar,newchar); 5,切割 String[] split(regex); 6,子串。获取字符串中的一部分。 String substring(begin); String substring(begin,end); 7,转换,去除空格,比较。 7.1 将字符串转成大写或则小写。 String toUpperCase(); String toLowerCase(); 7.2 将字符串两端的多个空格去除。 String trim(); 7.3 对两个字符串进行自然顺序的比较。 int compareTo(string);
-
StringBuffer是字符串缓冲区。
是一个容器。 特点: 1,长度是可变化的。 2,可以字节操作多个数据类型。 3,最终会通过toString方法变成字符串。
-
C create U update R read D delete
1,存储。 StringBuffer append():将指定数据作为参数添加到已有数据结尾处。 StringBuffer insert(index,数据):可以将数据插入到指定index位置。 2,删除。 StringBuffer delete(start,end):删除缓冲区中的数据,包含start,不包含end。 StringBuffer deleteCharAt(index):删除指定位置的字符。 3,获取。 char charAt(int index) int indexOf(String str) int lastIndexOf(String str) int length() String substring(int start, int end) 4,修改。 StringBuffer replace(start,end,string); void setCharAt(int index, char ch) ; 5,反转。 StringBuffer reverse(); 6, 将缓冲区中指定数据存储到指定字符数组中。 void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin) JDK1.5 版本之后出现了StringBuilder. StringBuffer是线程同步。 StringBuilder是线程不同步。 以后开发,建议使用StringBuilder 升级三个因素: 1,提高效率。 2,简化书写。 3,提高安全性。
基本数据类型对象包装类。
byte Byte
short short
int Integer
long Long
boolean Boolean
float Float
double Double
char Character
基本数据类型对象包装类的最常见作用,
就是用于基本数据类型和字符串类型之间做转换
-
基本数据类型转成字符串。
基本数据类型+"" 基本数据类型.toString(基本数据类型值); 如: Integer.toString(34);//将34整数变成"34";
-
字符串转成基本数据类型。
xxx a = Xxx.parseXxx(String); int a = Integer.parseInt("123"); double b = Double.parseDouble("12.23"); boolean b = Boolean.parseBoolean("true"); Integer i = new Integer("123"); int num = i.intValue();
-
十进制转成其他进制。
toBinaryString(); toHexString(); toOctalString();
-
其他进制转成十进制。
parseInt(string,radix);
集合类
1. 为什么出现集合类?
面想对象语言对事物的体现都是以对象的形式,所以为了方便对多个对象的操作,就对对象进行存储,集合就是存储对象最常用的一种方式。
2. 数组和集合类同是容器,有何不同
数组虽然也可以存储对象,但长度是固定的;集合长度是可变的。
数组中可以存储基本数据类型,集合只能存储对象。
3. 集合的特点
集合只用于存储对象,集合长度是可变的,集合可以存储不同类型的对象。
集合框架
-
为什么会出现这么多的容器?
因为每一个容器对数据的储存方式都有不同。 这个存储方式称之为:数据结构
Collection
|--List:元素是有序的,元素可以重复。因为该集合体系有索引。
|--ArrayList:底层的数据结构使用的是数组结构。特点:查询速度很快。但是增删稍慢。线程不同步。
|--LinkedList:底层使用的链表数据结构。特点:增删速度很快,查询稍慢。线程不同步。
|--Vector:底层是数组数据结构。线程同步。被ArrayList替代了。因为效率低。
|--Set:元素是无序(存入和取出的顺序不一定一致),元素不可以重复。、
|--HashSet:底层数据结构是哈希表。是线程不安全的。不同步。
HashSet是如何保证元素唯一性的呢?
是通过元素的两个方法,hashCode和equals来完成。
如果元素的HashCode值相同,才会判断equals是否为true。
如果元素的hashcode值不同,不会调用equals。
注意,对于判断元素是否存在,以及删除等操作,依赖的方法是元素的hashcode和equals方法。
|--TreeSet:可以对Set集合中的元素进行排序。
底层数据结构是二叉树。
保证元素唯一性的依据:
compareTo方法return 0.
TreeSet排序的第一种方式:让元素自身具备比较性。
元素需要实现Comparable接口,覆盖compareTo方法。
也种方式也成为元素的自然顺序,或者叫做默认顺序。
TreeSet的第二种排序方式。
当元素自身不具备比较性时,或者具备的比较性不是所需要的。
这时就需要让集合自身具备比较性。
在集合初始化时,就有了比较方式。
Set集合的功能和Collection是一致的。
-
Collection定义了集合框架的共性功能。
1,添加 add(e); addAll(collection); 2,删除 remove(e); removeAll(collection); clear(); 3,判断。 contains(e); isEmpty(); 4,获取 iterator(); size(); 5,获取交集。 retainAll(); 6,集合变数组。 toArray();
1,add方法的参数类型是Object。以便于接收任意类型对象。
2,集合中存储的都是对象的引用(地址)
什么是迭代器呢?
其实就是集合的取出元素的方式。
如同抓娃娃游戏机中的夹子。
迭代器是取出方式,会直接访问集合中的元素。
所以将迭代器通过内部类的形式来进行描述。
通过容器的iterator()方法获取该内部类的对象。
-
List集合
特有方法。凡是可以操作角标的方法都是该体系特有的方法。
增 add(index,element); addAll(index,Collection); 删 remove(index); 改 set(index,element); 查 get(index): subList(from,to); listIterator(); int indexOf(obj):获取指定元素的位置。 ListIterator listIterator(); List集合特有的迭代器。ListIterator是Iterator的子接口。 在迭代时,不可以通过集合对象的方法操作集合中的元素。 因为会发生ConcurrentModificationException异常。 所以,在迭代器时,只能用迭代器的放过操作元素,可是Iterator方法是有限的, 只能对元素进行判断,取出,删除的操作, 如果想要其他的操作如添加,修改等,就需要使用其子接口,ListIterator。
该接口只能通过List集合的listIterator方法获取。
-
LinkedList
LinkedList:特有方法: addFirst(); addLast(); getFirst(); getLast(); 获取元素,但不删除元素。如果集合中没有元素,会出现NoSuchElementException removeFirst(); removeLast(); 获取元素,但是元素被删除。如果集合中没有元素,会出现NoSuchElementException 在JDK1.6出现了替代方法。 offerFirst(); offerLast(); peekFirst(); peekLast(); 获取元素,但不删除元素。如果集合中没有元素,会返回null。 pollFirst(); pollLast(); 获取元素,但是元素被删除。如果集合中没有元素,会返回null。
泛型
泛型:JDK1.5版本以后出现新特性。用于解决安全问题,是一个类型安全机制。
好处
1.将运行时期出现问题ClassCastException,转移到了编译时期。,
方便于程序员解决问题。让运行时问题减少,安全。,
2,避免了强制转换麻烦。
泛型格式:通过<>来定义要操作的引用数据类型。
在使用java提供的对象时,什么时候写泛型呢?
通常在集合框架中很常见,
只要见到<>就要定义泛型。
其实<> 就是用来接收类型的。
当使用集合时,将集合中要存储的数据类型作为参数传递到<>中即可。
//泛型类。
什么时候定义泛型类?
当类中要操作的引用数据类型不确定的时候,
早期定义Object来完成扩展。
现在定义泛型来完成扩展。
//泛型类定义的泛型,在整个类中有效。如果被方法使用,
//那么泛型类的对象明确要操作的具体类型后,所有要操作的类型就已经固定了。
//为了让不同方法可以操作不同类型,而且类型还不确定。
//那么可以将泛型定义在方法上。
特殊之处:
静态方法不可以访问类上定义的泛型。
如果静态方法操作的应用数据类型不确定,可以将泛型定义在方法上。
? 通配符。也可以理解为占位符。
泛型的限定;
? extends E: 可以接收E类型或者E的子类型。上限。
? super E: 可以接收E类型或者E的父类型。下限
-
Map集合
Map |--Hashtable:底层是哈希表数据结构,不可以存入null键null值。该集合是线程同步的。jdk1.0.效率低。 |--HashMap:底层是哈希表数据结构,允许使用 null 值和 null 键,该集合是不同步的。将hashtable替代,jdk1.2.效率高。 |--TreeMap:底层是二叉树数据结构。线程不同步。可以用于给map集合中的键进行排序。 Map集合:该集合存储键值对。一对一对往里存。而且要保证键的唯一性。 1,添加。 put(K key, V value) putAll(Map<? extends K,? extends V> m) 2,删除。 clear() remove(Object key) 3,判断。 containsValue(Object value) containsKey(Object key) isEmpty() 4,获取。 get(Object key) size() values() entrySet() keySet() Map |--Hashtable:底层是哈希表数据结构,不可以存入null键null值。该集合是线程同步的。jdk1.0.效率低。 |--HashMap:底层是哈希表数据结构,允许使用 null 值和 null 键,该集合是不同步的。将hashtable替代,jdk1.2.效率高。 |--TreeMap:底层是二叉树数据结构。线程不同步。可以用于给map集合中的键进行排序。 和Set很像。 其实大家,Set底层就是使用了Map集合。
-
map集合的两种取出方式:
1,Set<k> keySet:将map中所有的键存入到Set集合。因为set具备迭代器。 所有可以迭代方式取出所有的键,在根据get方法。获取每一个键对应的值。 Map集合的取出原理:将map集合转成set集合。在通过迭代器取出。 2,Set<Map.Entry<k,v>> entrySet:将map集合中的映射关系存入到了set集合中, 而这个关系的数据类型就是:Map.Entry Entry其实就是Map中的一个static内部接口。 为什么要定义在内部呢? 因为只有有了Map集合,有了键值对,才会有键值的映射关系。 关系属于Map集合中的一个内部事物。 而且该事物在直接访问Map集合中的元素。
集合框架的工具类。
Collections:集合框架的工具类。里面定义的都是静态方法。
-
1、Collections和Collection有什么区别?
Collection是集合框架中的一个顶层接口,它里面定义了单列集合的共性方法。
它有两个常用的子接口,
List:对元素都有定义索引。有序的。可以重复元素。
Set:不可以重复元素。无序。Collections是集合框架中的一个工具类。该类中的方法都是静态的
提供的方法中有可以对list集合进行排序,二分查找等方法。
通常常用的集合都是线程不安全的。因为要提高效率。
如果多线程操作这些集合时,可以通过该工具类中的同步方法,将线程不安全的集合,转换成安全的。
Runtime对象
该类并没有提供构造函数。
说明不可以new对象。那么会直接想到该类中的方法都是静态的。
发现该类中还有非静态方法。
说明该类肯定会提供了方法获取本类对象。而且该方法是静态的,并返回值类型是本类类型。
由这个特点可以看出该类使用了单例设计模式完成。
IO(Input Output)流
- IO流用来处理设备之间的数据传输
- Java 对数据的操作是通过流的方式
- Java 用于操作流的对象都在IO包中
- 流按操作数据分为两种:字节流与字符流
- 流按流方向分为:输入流,输出流。
流常用基类
字节流的抽象基类:
inputStream, OutputStream。
字符流的抽象基类:
Reader,Writer。
注:由这四个类派生出来的之类名称都是以其父类名作为之类名的后缀。
如:InputStream的子类FileInputSteam。
如:Reader的子类FileReader。
字符流的特点
既然IO流是用于操作数据的,
那么数据的最常见体现形式是:文件。
那么先以操作文件为主来演示。
找到一个专门用于操作文件的Writer子类对象。FileWriter。
后缀名是父类名。 前缀名是该流对象的功能。
flush和close的区别:
flush刷新后,流可以继续使用,它是刷新流中的数据
close刷新后,会将流关闭。
需求:在硬盘上,创建一个文件并写入一些文字数据。
//创建一个FileWriter对象。该对象一被初始化就必须要明确被操作的文件。
//而且该文件会被创建到指定目录下。如果该目录下已有同名文件,将被覆盖。
//其实该步就是在明确数据要存放的目的地。
FileWriter fw = new FileWriter("demo.txt");
//调用write方法,将字符串写入到流中。
fw.write("abcde");
//刷新流对象中的缓冲中的数据。
//将数据刷到目的地中。
//fw.flush();
//关闭流资源,但是关闭之前会刷新一次内部的缓冲中的数据。
//将数据刷到目的地中。
//和flush区别:flush刷新后,流可以继续使用,close刷新后,会将流关闭。
fw.close();
IO的异常处理方式。
public static void main(String[] args) {
FileWriter fw = null;
try {
fw = new FileWriter("demo.txt");
fw.write("helloworld");
fw.flush();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (fw != null)
fw.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
IO文件的续写
//传递一个true参数,代表不覆盖已有文件。并在已有文件的末尾处进行数据续写
\r\n表示换行
FileWriter fw=new FileWriter("demo.txt",true);
IO读文件读取
单字符读取:
FileReader fr =new FileReader("d:\\demo.txt");
int ch=0;
while((ch=fr.read())!=-1){
System.out.println((char)ch);
}
fr.close();
}
批量字符读取:
FileReader fr = new FileReader("d:\\demo.txt");
char[] buff = new char[1024];
int num;
while ((num = fr.read(buff)) != -1) {
System.out.println(new String(buff, 0, num));// buff数组,0表示从什么位置开始,
//num表示读几个
}
fr.close();
文本文件复制:
原理:其实就是将C盘下的文件数据存储到D盘的一个文件中。
步骤:
1,在D盘创建一个文件。用于存储C盘文件中的数据。
2,定义读取流和C盘文件关联。
3,通过不断的读写完成数据存储。
4,关闭资源。
字符流的缓冲区:
缓冲区的出现提高了对数据的读写效率
对应类:BufferedWriter
BufferedReader
缓冲区的出现是为了提高流的操作效率而出现的。
所以在创建缓冲区之前,必须要先有流对象。
该缓冲区中提供了一个跨平台的换行符。newLine();
字符读取流缓冲区:
该缓冲区提供了一个一次读一行的方法 readLine,方便于对文本数据的获取。
当返回null时,表示读到文件末尾。
字节流:
InputStream(读)
OutPutStraeam(写)
字节流:
FileInputStream
FileOutputStream
BufferedInputStream
BufferedOutputStream
通过刚才的键盘录入一行数据并打印其大写,发现其实就是读一行数据的原理。
也就是readLine方法。
能不能直接使用readLine方法来完成键盘录入的一行数据的读取呢?
readLine方法是字符流BufferedReader类中的方法。
而键盘录入的read方法是字节流InputStream的方法。
那么能不能将字节流转成字符流在使用字符流缓冲去的readLine方法呢?
File
File类常见方法:
1,创建。
boolean createNewFile():在指定位置创建文件,如果该文件已经存在,则不创建,返回false。
和输出流不一样,输出流对象一建立创建文件。而且文件已经存在,会覆盖。
boolean mkdir():创建文件夹。
boolean mkdirs():创建多级文件夹。
2,删除。
boolean delete():删除失败返回false。如果文件正在被使用,则删除不了返回falsel。
void deleteOnExit();在程序退出时删除指定文件。
3,判断。
boolean exists() :文件是否存在.
isFile():
isDirectory();
isHidden();
isAbsolute();
4,获取信息。
getName():
getPath():
getParent():
getAbsolutePath()
long lastModified()
long length()
网络编程
- 网络模型
OSI参考模型
-
TCP/IP参考模型
OSI参考模型 TCP/IP参考模型
应用层 |
表示层 | 应用层
会话层 |
传输层 传输层
网络层 网际层
数据链路层 |
物理层 | 主机至网络层
网络通讯要素
-
IP地址
- 网络中设备的标识
- 不易记忆,可用主机名
- 本地回环地址:127.0.0.1 主机名: localhost
-
端口号
- 用于标识进程的逻辑地址,不同进程的标识
- 有效端口:065535,其中01024系统使用或保留端口。
-
传输协议
- 通讯的规则
- 常见协议: TCP UDP
- UDP
将数据及源和目的封装成数据包中,不需要建立连接
每个数据报的大小限制在64k内
因无连接,是不可靠协议
不需要建立连接,速度快 - TCP
建立连接,形成传输数据的通道
在连接中进行大数据量传输
通过三次握手完成连接,是可靠协议
必须建立连接,效率会稍低
-
Socket
- Socket 就是为网络服务提供的一种机制
- 通信的两端都有Socket
- 网络通信其实就是Socket间的通信
- 数据在两个Socket间通过IO传输。