javac –d . First.java
-d 指定生成的class文件存放的路径,连同包一起编译。
单行注释
//
多行注释
/*
*这是
*/
文档注释
/**
*主要用来生成API文档 Javadoc –version–author –d doc CommentTest.java
*/
2.标识符:类,方法,变量的名字
标识符的命名规则
(1)
3.关键字
4.基本数据类型
JAVA的数据类型的分类:
基本数据类型:
布尔类型:boolean
字符类型:char
整数类型:byte,short,int,long
浮点类型:float,double
引用数据类型:
类类型:class
接口类型:interface
数组类型:[ ]
强制类型转换:
(a) 显示的类型转换:高精度转低精度
byte b=(byte)200;
(b) 隐式的类型转换:低精度转高精度
long a=200(200提升精度为long)
12345+5432l=17777
double a=2,b=1.1;
System.out.println(a-b);
结果:0.899999999999999
变量的申明,int a;
变量的赋值:a=1;
变量的初始化:int a=1;
驼峰命名法:每个单词首字母大写,增加可读性.
类:把一组对象抽象出具有相同属性和行为的模板
对象:万物皆对象,现实世界中对象是实实在在的东西
运行时数据
方法区/代码区:存放类的信息
栈:存放局部变量
堆:存放动态数据,由new操作产生的数据
常量池:存放常量final修饰,常量池在堆区
pc寄存器:存放下一条要执行的指令
new操作对应内存中做哪些事情:
a. 在栈区分配一块空间保存对象的引用。
b. 在堆区分配一块空间保存对象本身的数据。
c. 将堆区的地址赋值给栈区对象的引用。
基本数据类型在内存分配中,在栈区保存数值本身
引用数据类型在栈区保存地址
第三章
1. 实例(全局)变量和局部变量
变量:先申明后赋值,再使用。
实例变量:放在堆区
位置:放在类里面,方法外面。默认值string类型:NULL,null+“字符串”=“null字符串”
作用域:在整个类当中
使用原则:系统进行默认赋值
生命周期:从(new对象)对象创建到GC回收对象结束
局部变量:放在栈区
位置:放在方法里面,放在{}里面。
作用域:从定义该变量到该方法结束。
使用原则:先赋值后使用。
生命周期:从变量定义开始到方法调用结束
作用域:变量的有效范围
生命周期:从该对象被创建被分配内存空间开始到该对象被销毁,所占内存空间被回收结束
找不到符号 说明变量还没申明就使用。
a+=b; 等价于 a=(short)(a+b)
+=: 做隐式的数据类型转换,向等号左边的数据类型转换
instanceof:判断这个引用类型的引用对象是否是这个类的实例
例:String str=”hello”
strinstanceof String 结果为true
strinstanceof Object 结果为true
等操作符 = 结果为true/false
比较基本数据类型的值,比较的是数据本身的值。
比较引用数据类型的值。比较的是对象的地址。
inta=20;
intb=10;
a==b;
Stringa1=”hello”
Stringa2=”hello”
a1==a2;
String a3=new String(“hello”)
String a4=new String(“hello”)
a1==a2;true 因为引用类型的hello在内存中保存在堆里的常量池中,a1,a2保存在栈中,都指向这个常量
a1==a3;false
a3==a4;false 因为hello被保存为堆里的对象,再new一个hello对象是重新开辟一个空间保存hello对象,a3和a4的地址不同
a3.equals()a4; true 因为equals比较的是对象的数据,真正的值
位移操作符 针对二进制来运算
>>:有符号位的右移 最高位补符号位
>>>:无符号位的右移 最高位补0
<<:左移 最低位补0
位操作符 针对二进制运算
&:位与 还可用在表达式上
|:位或
^:异或 相同为0,相异为1,可看成不进位的相加
~:非
(g)三目运算符 ? : 有隐式的类型转换
(f)逻辑操作符 &&和|| 结果为true/false 不能用在位操作符上
&&:只要有一个条件为假,结果就为false。如果前面的表达式为假,短路,直接为假,不执行后面的表达式
||:只要有一个条件为真,结果就为true。如果前面的表达式为真,短路,直接为真,不执行后面的表达式
基本数据类型:
隐式的数据类型转换:精度低转成精度高的
如果转之前是有符号位,最高位补符号位
如果是无符号位,最高位补0
显式(强制转换)的数据类型转换:精度高转成精度低
最低位截取;
引用数据类型:
隐式的数据类型转换:将子类对象转成父类
显式的数据类型转换:将父类对象转成子类
第四章 语句
1.判断语句(条件语句)
if…else语句
单分支if(条件){…}
双分支if(条件){…}else{…}
多分支if(条件1){…} else if(条件2){…} else if(条件3){…}
1)if 后的条件,必须是Boolean表达式,不能用数字
2)最多只有一个分支执行
f)如果只有
switch语句
switch(变量或者表达式(byte,short,char,int,[string]jdk1.7)){
case 值1 : 代码1;
case 值2: 代码2;
…….
}
(1)根据switch后的变量的值区找匹配的case。如果找到之后会以它为程序的入口继续向下执行,执行下一个case语句的内容而不看后面case的条件,直到碰到break才会结束switch语句
(2)case后数据的值的数据类型必须和switch后的变量的数据类型匹配
(3)case的值不能是不同的
(4)所有case语句都没有匹配成功,会执行default语句,default语句可以放在switch中的任何位置,但是放在前面需要加break,否则会执行break后面的case代码。
(5)switch括号里变量的数据类型:byte,short,char,int
jdk1.7后可以用string,enum
(6)多个分支可以执行同一条语句即case 1:case 2:case 3 :语句;
2. 循环语句
4个部分
初始化:虚幻的控制变量做初始化
循环条件:循环体是否执行的条件
循环体:重复执行的代码
迭代部分:改变循环的控制变量,达到改变循环条件的值
(1) for
for(初始化;循环条件;迭代部分){
循环体
}
先执行初始化,再执行循环条件,执行循环体,最后执行迭代部分。
(2)while
初始化
while(循环条件){
循环体
迭代部分
}
(2) do{
}while(循环条件)
break:中断当前所在循环语句或者指定循环(想跳出某个循环语句时,在该语句前加“标签名:”,然后break 标签名)
continue:中断本次循环,继续下一次循环,不跳出所在循环。(想跳到某个循环语句的下一个循环体时,在该语句前加“标签名:”,然后continue 标签名)
第五章 数组
数组是用来存放具有相同数据类型的元素的有序集合;
数组和链表的区别
(a)在内存分配上
数组要求分配一块连续的内存空间
链表不要求分配一块连续的内存空间
(b)在项目需求上
项目重点在增删改的操作 -----链表 链表不需要数据的搬移
项目重点在查询的操作 -----数组 数组的检索效率高
3.使用数组
(1)申明数组
基本数据类型的数组
int[] array in array[ ]
(2)给数组赋值
array=newint [5]; //动态初始化
array[0]=20;
int[] array =new int[ ]{5,67,39,384};//静态初始化
int[] array={83,35,773,25};
错误形式int[ ] array= new int[3]{53,67,69}
int[] array; array={3,5,67,4} //动态初始化和静态初始化不能一起使用
二位数组的初始化不能先初始化列,再初始化行。
System.arraycopy() 拷贝数组
System.arraycopy(源数组对象的引用,源数组中拷贝数据的起始位置,目标数组对象的引用,把数据放到目标数组的起始位置,从源数组中拷贝数组的长度)
可变长参数(int… num)
第六章 对象和类
多态:同一领域(继承同一个类或者实现同一个接口)的不同对象调用相同的方法表现不同。
抽象数据类型-----class
元数据:描述数据的数据
参数传递:把实参传递给形参
基本数据类型传递的是数值
引用数据类型传递的是地址。
this
用法:
1.用在实例变量上 //this.变量
用来区分具体相同名字的实例变量和局部变量
2.this调用本类方法 this.方法(参数列表)
3.this调用构造器,只能放在第一行 //this(参数列表)
5.数据隐藏------封装
作用----避免用户的非法输入
将类中属性和方法进行隐藏
属性隐藏:将属性定义成private的访问修饰符
提供统一的接口给用户(提供属性的set,get方法)
方法隐藏:隐藏方法的具体实现,也可以将方法修饰符定义成private
6.方法重载-------解决功能相同,数据的类型不同
发生在本类中,方法名字相同,参数列表不同(参数个数不同 或 参数类型不同,或 参数顺序不同),,返回值可以不同对重载没影响,抛出异常可以不同
7.创建对象和初始化对象
初始化对象:给对象中属性的赋值
创建对象new操作所做的是:
(1)在栈区分配一块空间保存对象的引用
(2)在堆区分配一块空间保存对象
(3)将堆区的地址赋值给栈区的引用
(4)系统会给属性做默认的初始化
(5)系统会给属性做显式的初始化
所有的对象的该属性的值都一样就可以用显式初始化
Person类
privateint maxAge=120;
(6)调用代码块{ }来初始化
(7)调用构造器给属性做初始化
根据用户提供的数据给属性进行初始化的
构造器可以重载,
系统会提供一个无参数的构造器—默认构造器。如果该类定义其他的构造器, 默认构造器就无效了,需要显式的提供无参数的构造器。
继承extends
1.子类继承父类的所有属性和方法,可以继续在此基础上进行扩展
子类不能继承父类的构造器
好处:代码复用,简化编程
注意事项:
1创建一个子类对象系统必须先创建一个父类对象
2在子类构造器中系统会默认调用父类的无参构造器,隐含有一句代码:super();
3如果父类无参构造器失效,就需要在子类构造器中显示的调用父类存在的构造器。 sup
2.super代表父类对象, this代表当前对象
super用在实例变量。指定使用父类的实例变量(很少用)。
super用在方法上。指定调用父类的方法。
super用在构造器上。指定调用父类的构造器
3.方法的重写,从父类继承的方法无法满足子类的需求,子类就可以重写该方法。
条件: 发生子父类中
方法名必须相同
参数列表必须相同
返回值类型必须相同
可见性不能变小
异常不能抛大
@Override:注解。用来告诉编译器这是一个重写方法,编译器就会检查是否满足重写方法的条件。如果不满足,就在编译期报错,错误尽量控制在编译期。
4.多态
同一领域(继承同一个类或者实现同一个接口)的不同对象调用相同的方法表现不同。
条件:父类的引用指向子类对象
子类要重写父类的方法
一个变量可以有多种数据类型:
Personp1=new Student();
Personp2=new Teacher();
p1 编译期的数据类型 Person
运行期的数据类型 Student
p2 编译期的数据类型 Person
运行期的数据类型 Teacher
p1真正的数据类型由运行期的数据类型决定
5.引用数据类型的转换
把子类对象给父类对象(隐式)
Personp=new Student();
把父类对象给子类对象(需要强制类型转换),是否转换成功要看对象实际的数据类型
在进行数据类型转换之前需要先判断。通过instanceof判断该对象是否属于该类的实例。还可以判断该对象是否属于该类子类的实例
Students=(Student)p
对象与对象之间的关系
is a 继承关系
use a 使用关系,通过方法的参数来使用对象
has a 包含关系,将一个对象通过实例变量的形式申明在另一个对象中
组合:整体和部分同时存在,同时消亡。
整体对象一旦不存在,部分对象也不存在了。
//在整体类添加部分类的对象属性,构造方法对部分进行初始化,并添加get方 法,没有set方法
聚合:整体和部分不是同时存在,也不是同时消亡。
整体对象不存在,部分对象还存在。
//在整体类添加部分类的对象属性,并添加set方法和get方法。测试类需要创建 部分类的对象,并调用整体类的set(部分类的对象)方法
1.static
(1)修饰变量 1只能修饰实例变量,不能修饰局部变量
2静态变量是类中每个对象共享的,非静态变量是每个对象都特有的
3静态变量存放在方法区,非静态变量存放在堆区
4静态变量是属于类的 类名.变量名
非静态变量是属于对象的 对象名.变量名
5静态变量是从类加载的时候开始有的,
非静态变量是从对象创建的时候开始有的
(2)修饰方法
1静态方法的调用 类名.方法名
非静态方法的调用 对象名.方法名
2静态方法不能访问非静态变量
非静态方法可以访问静态的变量
静态方法在类加载就有了,非静态变量在类加载之后创建对象才有。
3静态方法不能被静态方法和非静态方法重写
没有多态效果
4静态方法属于类
5静态方法不能使用this ,super。
(3)修饰初始化块 初始化块位置:类里面,方法外面
1初始化块:{}
调用:在new对象时被调用,调用n次
功能:一般用来给实例变量赋值
2静态初始化:static{} 把只需要执行一次的代码放在静态初始化中
调用:在类加载时被调用,只调用一次
功能:一般用来给静态变量赋值
(4)修饰import----------静态导入,导入的方法可以直接使用方法名调用方法,但程序的可读性会变低,因为直接使用方法名,不知道是哪个包里的
importjava.lang.Math;
Math.random();
importstatic java.lang.Math.*;
random();
单例模式:在整个项目从开始到结束的过程中,该类只能产生一个对象。
做法:将构造器改为private。
懒汉式:需要对象的时候才创建对象,提供一个返回值为该类对象的方法
饿汉式:一开始就把对象创建好 。在静态初始化块创建对象
2.final
(1)修饰变量---à常量
1可以修饰实例变量,也可以修饰局部变量
2final修饰的变量必须显式的赋值
final修饰实例变量时,可以在变量申明时赋值或者在构造器中赋值
final修饰静态变量时,需要在变量申明时赋值,可以在静态代码块内初始化, 不能在构造器中赋值
3final修饰的变量的值不能被修改
(2)修饰方法 该方法不能被重写
(3)修饰方法 该方法不能被继承
3.abstract抽象
(1)修饰方法-------抽象方法
1当不知道方法的具体实现是什么,就可以定义一个抽象方法。没有方法体
2功能:定义了一系列的规范,描述一个类具有哪些功能,但是不会实现这些功能, 由子类去重写该抽象方法
(2)修饰类----------抽象类
1一个类中有抽象方法,该类必须定义成抽象类
2如果一个类是抽象类,该类可以没有抽象方法
3抽象类中可以定义实例变量,静态变量,构造器,非抽象方法和抽象方法
4抽象类不能实例化对象,抽象类的构造器是给创建子类对象使用的
5主要用途:给子类继承
6一个类去继承抽象类,子类需要重写抽象类中所有抽象方法。或者将子类再一次 定义成抽象类
接口
作用:定义一系列的规范,描述该类,该接口有哪些功能,功能没有具体实现
解决了java语言的单继承
C语言,c++都是多继承,java是单继承,java语言退步?
答:多继承不好:造成代码的浪费,造成继承的多义性
java提供了接口解决单继承,实现多继承,
1是抽象类的完全抽象,接口中所有的方法都是抽象方法
2接口中声明的变量默认都是publicstatic final 修饰,需要对该变量进行显示的赋值(因为是final),
3接口的方法默认都是publicabstract 修饰
4接口没有构造器,接口不能实例化
接口实现多继承,接口描述功能
一个类实现多个接口,需要重写接口的所有方法
一个接口可以继承多个接口,一个类只能继承一个类,但能实现多个接口
访问控制权限:可见性
顶层类用public和默认修饰
包装类:针对于基本数据类型对应一个类类型,把这个类类型称为包装类
(1)java要求所有的操作
int---------------------Integer char-------------------Character
byte------------------Byte short-----------------Short
long------------------Long boolean-------------Boolean
float-----------------Float double--------------Double
装箱:把基本数据类型转换成包装类的过程
new操作
包装类.valueOf(基本数据类型)方法:Double.valueOf(2.4); Boolean.valueOf(true);
拆箱:把包装类转换成基本数据类型的过程
调用 包装类对象.Xxxvalue()方法
JDK1.5提供了自动装箱和自动拆箱
==和equals()
对于引用数据类型
==判断两个对象的地址是否相同
equals()判断两个对象的值是否相同
如果一个类没有重写equals()方法,那么equals()方法就和== 是一样的效果,比较两者的地址
equals()是Object类中
重写equals(Object)的规则:
1.判断传进来的对象是否是空对象 return false
2.判断传进来的对象是否是当前对象 return true;
3.判断传进来的对象和当前对象的数据类型是否相同
4.自定义比较规则
toString() 输出一个对象的时候默认输出地址 格式:类的权限类名+@十六进制的地址
输出一个对象的时候想输出对象里面真正内容,就需要重写toString()方法
toString方法来自Object类,输出对象是默认调用tostring()方法
innnerClass 内部类
内部类:将类定义在类里面或者方法中或者表达式
顶级类:定义在package下的类
内部类放在不同的位置进行分类:
静态内部类 将内部类定义在类里面,方法外面,并且由static修饰的类,相当于静态 变量,静态方法,允许出现静态属性和方法
访问权限:只能直接访问外部类的静态资源,不自动持有外部类的对象
需要通过外部类的对象访问外部类的非静态资源
成员内部类 定义在类里面,方法外面,相当于成员方法/成员变量,不能定义静态资源
访问权限:可以访问外部类的一切资源,自动持有外部类的对象
局部内部类 定义在方法中,相当于局部变量,不能用修饰符,只能用默认的,只能定 义非静态资源(用的很少)
访问权限:可以访问修改外部类的资源,只能访问所在方法的final修饰 的局部变量(jdk1.7以前,1.8能但不能修改),只能被当前的方法访问
访问外部类资源 类名.静态变量 类名.this.非静态资源
匿名内部类 定义在方法中或者参数中,没有类名的类,没有class关键字
用一个接口或者抽象类的名字来代替创建了一个匿名内部类。匿名类没有 名字,没有class关键字,不能定义静态资源
访问权限:可以访问外部类的一切资源,还可以访问该方法中final修饰 的局部变量
非静态内部类中不允许定义静态成员。仅允许在非静态内部类中定义静态常量static final。
内部类中如何访问外部类的资源
静态内部类:静态变量/方法直接使用名字,不能直接访问外部类非静态资源,需要创建外部类对象
成员内部类:外部类对象.this.变量
外部类中如何访问内部类的资源
静态内部类:直接用内部类类名访问静态资源,用内部类实例访问非静态资源
成员内部类:不能直接访问,需要创建内部类对象
外部类中如何创建内部类的对象
静态内部类:直接new内部类对象
成员内部类:直接new内部类对象
局部内部类:new
在其他类中如何创建内部类的对象
静态内部类:外部类.内部类对象=new 外部类. 内部类() // 不需要外部类对象
成员内部类:外部类.内部类对象=new 外部类(). new 内部类()//得先有外部类的对象
内部类的功能:1分担外部类的功能
2避免命名冲突
3
4
第七章 集合
集合:java版本的数据结构,保存数据和操作数据 java.util包
集合框架:简化编程
collection:接口,定义保存单值的规范
Set接口,定义保存不可重复无序的单值规范
--HashSet实现类,哈希算法来保存数据,检索效率比较高
--TreeSet实现类,定义排序规则
--SortedSet接口,在Set基础上进行排序规范
List接口,定义保存可重复有序的单值规范
--ArrayList实现类,使用数组保存数据,线程不安全,效率高
--LinkedList实现类,使用链表保存数据
Map接口,定义保存键值对的规范 (key,value)key是唯一的------------------不能用for each
--HashMap实现类,哈希算法保存数据
线程不安全的,效率高 在增删改查外面加锁可以线程安全
可以添加控制,key=null,value=null;
--Hashtable实现类,哈希算法保存数据,线程安全的,效率低
不可以添加控制,key!=null,value!=null;
--SortedMap接口,在Map基础上进行排序的
--TreeMap实现类,根据key进行排序
增强for循环(for each)---------------只能遍历实现了Iterable接口的集合
for(数据类型 临时变量:数组/集合对象的引用){
System.out.println(临时变量);
}
缺点:无法知道元素在数组或者集合在哪个位置
向Set集合中添加元素,
先判断两个对象的hashCode的值是否相同
如果hashCode不同,就不会判断equals方法,两个对象不是同一个对象
如果hashCode 相同 ,才会判断equals方法的值,如果equals方法的值相同,两个对象才是同一对象
hashCode的值用来决定对象存在Set集合的哪个位置的
重写hashCode方法建议相同的对象放在相同的位置
建议:将所有会影响判断对象相同的属性的hashCode的值相加
TreeSet,TreeMap(根据key)的排序
(1)自然排序
将需要排序的类实现java.lang.Comparable及重写接口中方法
public int compareTo(Object obj){
//指定排序规则
}
(2)覆盖排序
在创建TreeSet对象的时候指定比较器对象(实现了comparator接口的匿名内部类)
覆盖排序优先级更高
向集合中放数据,默认放的是Object,取出来也必须是Object
取出Map集合的数据方法
(1)Set keyset() : 将Map集合中所有的key取出来放在Set集合中,再通过key获取对应的value
(2)Set entrySet() :将Map集合中的key和对应的value取出来创建成一个新的对象,然后把这个新的对象放在Set集合中,新对象就是Map.Entry对象
Map.Entry对象维护一个Key和对应的value
getKey() getValue()
(3)Collection values():取出Map中所有的value放在Collection集合中,不能用value获取key值
泛型:参数化类型
泛型只在编译期有效
List<Integer> list=newArrayList<Integer>(); //正确写法
List list=new ArrayList<Integer>(); //等于没加泛型,list可以添加任意元素
List<Integer> list=newArrayList<>(); //jdk1.7以后,菱形语法,钻石语法,不存在子父类,即等号左右的泛型参数不能是子父类,只能是同一个
通配符?
?匹配任意一个数据类型
<? extends supClass>:上界限定 ?只能匹配supClass以及supClass的子类
<? super subClass>:下界限定 ?只能匹配subClass以及subClass的父类
使用通配符不能进行add的添加,即xxx.add();,因为在编译的时候没有指定数据类型。
泛型方法放在普通类当中,需要在返回值的前面说明它是泛型参数,加上<E>,E为普通类包含的泛型参数
外界传入参数:
(1)Properties:以键值对的方式来保存数据,键值都是String类型
a.读取JVM的系统配置信息
b.设置JVM系统参数 -D
(2)应用程序参数
main(String[] args){}
获取:第一个数据:args[0] 第二个数据:args[1] .....
3)使用文件(key=value)
文件名:info.properties
程序中写文件的路径:src/com/briup/reflect/info.properties)
第八章 反射
自描述,自定义,一个对象或者类获得自身的Class对象的过程称为反射
通过Class可以获取到class的所有信息
比如获取class中有哪些属性,方法,构造器
通过Class创建class的对象,给class中私有属性赋值,调用class中的所有方法(包括 私有)
对象---抽象--->class---抽象化-->Class
Class-->具体化-->class-->具体化-->对象
使用反射的步骤:
(1)获取类镜像-----Class
1Class.forName(String className)
2数据类型.class
3对象.getClass()
(2)基于类镜像去创建class的对象
(3)基于类镜像去操作class的对象的属性,方法和构造器
第九章 异常
改变程序正常执行流程的意外情况
异常是对象,java.lang.Exception
异常处理
try{
//尽可能放可能出现异常的代码
}catch(异常的数据类型 对象的引用1){
//处理异常的代码1
}catch(异常数据类型2 对象的引用2){
//处理异常的代码2
}finally{
//
}
抛出异常:在try中的逻辑代码碰到异常,由java运行时环境创建异常对象并抛出的过程叫 做抛出异常。
捕获异常:由catch来捕获相应的异常,如果catch没有捕获相应的异常,会把异常抛给java 运行环境。java运行环境会直接中断应用程序,并且会打印异常栈的信息。异 常栈的信息会知道在哪行代码出现了什么样的异常。
处理异常:在catch的代码块中处理异常。
注意:多个catch,小类型放在前面,大类型放在后面,finally块不能有return语句
异常的分类
Object
--Throwable
--Error 系统级别的错误,程序员无法控制
--Exception 程序员处理异常,异常来自Exception以及Exception的子类
--RuntimeException 运行时异常
--非RuntimeException 编译时异常
unchecked异常:RuntimeException异常以及子类,运行时异常,不可修复的异常,如数据 库连接失败
NullPointerException,ArithmeticException
checked异常:非RuntimeException异常以及子类,编译时异常。可修复的异常,在编译的 时候需要处理,如输入用户名错误
ClassNotFoundException
异常的处理方式:
(1)try…catch 自己处理异常
(2)throws 自己处理该异常就需要抛出异常,给调用者处理异常throws放在方法申明的地方,throws后面加异常类型
原则:自己能处理的异常尽量自己处理异常,尽量在main方法中处理异常而不是抛出
throw 放在方法体中,后面跟的是异常对象
throws 放在方法申明的地方,后面跟的是异常类型
自定义异常:在项目中建议不抛出系统异常,因为异常的类名通常应该包含该异常的有用信息。应该选择合适的异常类,从而可以明确的描述该异常情况,就应该选择自定义异常
自定义checked异常 需要extendsException
将unchecked 异常捕获,catch语句中抛出一个checked异常,再在main方法中处 理checked异常
自定义unchecked异常 需要extendsRuntimeException
断言
assert 条件:“字符串”
如果条件为true,程序向下执行
如果条件为false,输出冒号后面的字符串信息,程序不会向下执行
断言默认是关闭的,运行程序的时候打开断言,传递一个VM级别的参数-ea
第十章 GUI
1.组件
(1)容器:可以存放其他组件的组件
(2)普通组件:不可以存放其他组件,Button
2.布局管理器:决定组件放在容器的哪个位置,以及组件放在容器中大小
3.时间监听器:处理组件发生的事件
2.GUI编程有关包:
1.java.awt.*
(1)放所有的组件和容器。 组件提供统一的显示风格,已被淘汰
(2)所有的布局管理器
(3)字体的设置以及颜色的设置
2.javax.swing.*
放所有的组件和容器。 组件是根据系统来显示风格如JButton
3.GUI编程
(1)选择容器
Component
Container
Window 默认是BorderLayout布局
Frame:可以变大变小,移动,可以独立存在,是顶级容器,不能放在其他容器中
Dialon:不能变大小,可移动,可以独立存在
Panel:不能独立存在,依赖于Window系列存在,默认是FlowLayout布局
ScrollPanel
(2)选择布局管理器
FlowLayout:流式布局,居中从左向右依次排序。第一行排满之后,接着排第二行……
BorderLayout:边界布局
GridLayout:网格布局
CardLayout:卡片布局
(3)添加组件到容器中
(4)添加事件监听器
JTextField:单行文本输入框
JTextArea:多行文本输入框
JLable:
pack()方法:用此方法可以不写setSize()方法,根据组件区自动扩充容器的大小,一定要在添加组件之后调用,即在调用init方法后
AWT的事件处理模型
回调方法:该方法程序员没有调用,但是该方法在某一个时间点被调用。
AWT的事件处理模型有三大元素:
事件源:产生事件的对象,组件
事件对象:描述事件的详细信息,从事件对象中获取事件源,获取产生事件时的坐标
获取产生事件时的哪一个键盘。 命名规则:XxxEvent
事件监听器:监听事件源是否产生事件。
如果事件源产生了事件,就需要做相应的处理事件的操作。
命名规则:XxxListener
计算按钮-------------事件源
ActionListener-------事件监听器
ActionEvent------- ---事件对象
事件适配器:空实现事件监听器,XxxAdapter
classMouseAdapter implements MouseListener{
publicvoid mousePressed(MouseEvent e){}
}
classTest extends MouseAdapter{
}
label.addMouseListener(newMouseAdapter(){
publicvoid mousePressed(MouseEvent e){
}
javax.swing.Timer 定时器:每隔一段时间做重复的事情
第十一章 多线程
1.线程:是程序执行的最小单元
一个进程可以启动多个线程,至少要启动一个线程。线程不是独立存在,必须依赖于进程的
线程和进程的目的:达到多任务,提高执行的效率
同时性:在一个时间段上
2.线程的三要素
CPU:只有抢占到CPU,该线程才可以执行。 多线程共享CPU
代码:线程执行的是run方法中的代码 多线程共享同一个类的run方法的代码
数据:变量(局部变量不共享,实例变量,静态变量共享)
继承Thread之后,实例变量不共享
实现Runnable之后,实例变量共享
线程有自己的栈空间
3.线程的使用
(1)构建线程类 1继承Thread类,重写run方法 继承之后该类就是一个Thread类
或2实现runnable接口重写run方法, 实现之后该类不是一个Thread类
(2)创建线程对象
1Thread t=new Test();
或2Runnable r=new Test();
Threadt=new Thread(r);
(3)启动线程------不是马上执行,会等待CPU的调度 线程对象.start();
4.为什么JAVA会提供两种方式来实现线程类?
JAVA是单继承
首选继承Thread。更符合面向对象编程的思想,实现Runnable是因为java是单继承
5.Thread类中提供的方法:
getName():获取当前线程的名字,系统默认给线程取一个名字,名字格式Thread-num
staticsleep(睡眠时长):单位毫秒,让当前进程进入睡眠状态
staticcurrentThread():获取当前线程的对象
6.线程的状态转换
新建状态:通过new创建一个线程对象,该线程处于新建状态,没有调用start()方法
就绪状态:调用start()方法后进入到就绪状态,线程已经准备就绪,等待CPU调度
就绪状态的线程会进入到线程池中,CPU的调度就从线程池中调度
运行状态:CPU正在调度该线程。运行状态会执行run方法中的代码
死亡状态:运行状态中的线程执行完run方法,该线程进入死亡状态。
阻塞状态:等待状态,锁状态,睡眠状态都是阻塞状态,代码停在run方法,阻塞状态下的线程可以接收某些条件之后可以进入就绪状态。
新建状态--->就绪状态 就绪状态--->运行状态
运行状态--->死亡状态,阻塞状态,就绪状态 阻塞状态--->就绪状态
7.中断线程
join():线程等待,等待该线程结束当前所在的线程才能结束
interrupt():只能中断睡眠线程,将睡眠状态的进程变成就绪状态,如果中断运行中的线程,会报错
isInterrupted():判断是否被中断
static interrupted():清空中断信息
(1)使用共享标识变量来中断进程
8.线程的并发访问问题
多线程同时访问同一个对象所引发的问题
加对象锁每一个对象都有一把对象锁,线程想执行必须先拿到对应对象锁
9.synchronized用法
(1)synchronized(共享区){
临界区
}
共享区:多个线程同时操作的同一个对象
临界区:对共享区有影响的代码
如果线程想要执行临界区的代码,必须获取共享区的对象锁,临界区的代码最多只能让一个线程进入执行。该线程执行完临界区的代码之后释放对象锁。其他线程才有机会抢对象锁。
把加了synchronized关键字之后,要访问临界区代码的这些线程称之为互斥线程,互斥线程执行时没有顺序,谁先抢到对象锁和CPU,谁就先执行。
线程安全的类:该类的所有方法都实现线程安全,该类就是线程安全的类。
(2)synchronized放在方法申明的地方,获取当前对象的对象锁,方法中所有方法体都是临界区
10.线程之间的通信------操作的是同一个对象
同步线程:线程之间执行有顺序,相互之间有影响
互斥线程:线程之间执行是没有顺序,相互之间没有影响,谁先抢到CPU和对象锁就谁先执行
线程通信的步骤
(1)找共有对象
(2)使用放在synchronized关键字中的 wait(),notify(),notifyAll()方法。
wait():消费者等待生产者生产好产品之后的通知
notify():生产者生产好产品之后通知某一个等待的消费者
notifyAll():生产者生产好产品之后通知所有等待的消费者
这三个方法来自Object类。基于对象来操作,必须放在synchronized关键字中
(3)先wait(),后notify(),使用标识变量
sleep():不会释放对象锁
wait(): 会释放对象锁
11.死锁 多个线程同时操作多个对象就很容易产生死锁
解决方式:多个线程在加对象锁的时候一定要按照相同的顺序添加
12.Thread方法
setPrioirity(int 优先级值):设置线程的优先级。优先级值的范围是1-10,级数越大,优先级越高;优先级越高,线程不一定会先执行
Thread.yield():当前线程释放CPU的执行权,让其他线程执行,线程临时暂停
第十二章 IO流
1.流:流是一组有序的的数据序列,在JAVA中把流称之为采用统一的操作方式去读写数据。
流是对象,java.io
2.流的分类
(1)根据流操作数据的最小单位
1字节流:字节的读写 流名字后面是InputStream,OutputStream
2字符流:一个一个字符的读写,两个两个字节的读写
还可以在不同字符编码之间进行转换 流名字后面是Reader,Writer
(2)根据流的方向,参照物是当前程序
1输入流:从其他地方将数据读入当前程序中 InputStream,Reader
2输出流:从当前程序中写出数据到其他地方 OutputStream,Writer
其他地方:文件,网络
字节输入流,字节输出流
字符输入流,字符输出流
InputStream,OutputStream
抽象类,定义如何读写字节的规范,是所有字节输入流,输出流的父类
read():一个字节一个字节读取
read(byte[]):一次读取多个字节
read(byte[],int,int):一次性读取byte数组里指定起始位置开始指定长度个数据
write(int 字节):一个字节一个字节的写
write(byte[]):一次性写byte数组字节
write(byte[],int,int):一次性写byte数组里指定起始位置开始指定长度个数据
3.FileInputStream,FileOutputStream
针对文件操作
4.BufferedInputStream,BufferedOutputStream
带有缓冲区的流,基于缓冲区在读写数据。作用:提高读写数据的效率
当缓冲区满了就会自动刷新到文件中。包装流:可以包装其他的流
flush():带有缓冲区的流一定要在流关闭之前手动刷新一次,将缓冲区的数据属性到输出流中。
5.DataInputStream,DataOutputStream
包装流,过滤流。 主要用于读写基本数据类型的数据
6.ObjectInputStream,ObjectOutputStream
包装流,过滤流。 主要读取类类型(对象)的数据
7.序列化:把程序中的对象写出到文件或者网络中的过程
反序列化:把文件中获取网络中的对象读取到当前程序中的过程。
一个对象如果想实现序列化或者反序列化,必须让该类实现java.io.Serializable的接口
java.io.Serializable没有属性和方法,是空接口
作用:起到了标识的作用,标识该类可以进行序列化和反序列化的功能
serialVersionUID的作用:1兼容不同版本的JVM
2如果修改了该类,也能够反序列化成功
3实现序列化之后,必须显式提供该属性的值,该属性的值可以采 用默认的UID,也可以自定义数字,也可以使用工具生成UID的值
8.PipedInputStream,PipedOutputStream
管道流,主要用于线程间的通信
connect():把管道输入流和管道输出流连接起来,还可以通过构造器的方式去连接起来。
9.Reader,Writer
抽象类,是所有字符输入流、输出流的父类,定义读写字符的规范
charread()
read(char[])
writer(char)
writer(char[])
10.FileReader,FileWriter
针对文件的字符操作
11.BufferedReader,BufferedWriter
StringreadLine()
write(String)
newline();
12.PrintWriter,PrintStream
输出流
PrintWriter既可以包装字节流,也可以包装字符流,但只能写字符数据
PrintStream只能包装字节流。既可以写字节数据,也可以写字符数据
传输文件首选字符流,要将字节流转换成字符流
字符流就是字节流的基础上加了字符编码
读写二进制的文件,必须用字节流
二进制文件(图片,视频,音频)
获取网络中的资源都是字节流
13.InputStreamReader / OutputStreamWriter
转换流
字节流转换成字符流 / 字符流转换成字节流
14.RandomAccessFile
既是输入流,也是输出流,支持在文件的任何位置进行随机读写操作
read()
write()
seek(long):跳过多少个字节。使用大文件的多点下载和多点拷贝的时候使用
第十三章 网络编程
C/S:客户端和服务器端
B/S:浏览器和服务器端
java.net
ServerSocket
DatagramSocket
java.io
java.lang.Thread
TCP协议:是一种比较可靠的协议。在服务器端和客户端进行数据通信之前要使用3次握手协议建立连接。数据不会丢失,数据可以重发。成本比较高。如:文件下载
UDP协议:是一种不可靠的协议。不会建立连接。直接发送数据包,数据包里面包含数据要到达的目的地。数据会丢失。成本比较低。如:视频聊天
基于TCP协议的编程, 又称为Socket编程
(1)服务端的编程步骤
1创建ServerSocket对象,并且绑定端口号
2等待客户端的连接accept()。如果连接成功,服务器端就会获取到Socket对象
3基于Socket对象读写数据。
socket.getInputStream()获取输入流
socket.getOutputStream()获取输出流
4关闭资源
(2)客户端的编程步骤
1创建Socket对象,并且绑定IP地址和端口号。
2基于Socket对象读写数据的操作
socket.getInputStream()获取输入流
socket.getOutputStream()获取输出流
3关闭资源
IP地址:可以找到网络中唯一的一台计算机 192.16.0.10
端口号:可以找到该计算机中唯一的一个应用程序。端口号范围:0-65535,建议1024-65535
URI:统一资源标识符
URL:统一资源定位符
URN:统一资源命名符
枚举enum:可以控制取值范围。取值范围必须是枚举值中的一个。
当取值是一个范围就可以定义枚举
如:性别,星期,月份