一、 java开发工具Editplus:Editplus与jdk的连接配置,如:javac(编译)、java(运行)、javap(查看字节码)
a) 配置内容:
i. javac(编译):参数为 -d . $(FileName);初始目录 $(FileDir)
ii. java(运行):参数为 $(CurSel).$(FileNameNoExt);初始目录:$(FileDir)
iii. javap(查看字节码):参数为 $(FileNameNoExt);初始目录:$(FileDir)
二、 java初始:
a) 通过HelloWorld类讲解了关键字、命名规范、修饰符;
pubic class HelloWorld{
public static void main(String[] args){
System.out.println("Hello World!");
}
}
b) jdk与jre的区别;内容、范围///开发、运行//里面包含了各种类库和工具、java程序的运行环境JVM
jar;java下的压缩文件
javac;编译
javadoc;可形成帮助文档
共有:java;运行
native2ascii;本地码改成ASCII码
javap;查看字节码文件
c) 字节码;是java跨平台的一个机制,是一段二进制代码,是一种包含执行程序、
由一序列 op 代码(操作码)/数据对组成的二进制文件。字节码是一种中间码,它比机器码更抽象,是包含一个执行程序的二进制文件(.class)
数据单位的进制;K是千 M是兆 G是吉咖 T是太拉 8bit(位)=1Byte(字节)
1024Byte(字节)=1KB 1024KB=1MB 1024MB=1GB 1024GB=1TB
java中,字节码是CPU构架(JVM)的具有可移植性的机器语言。
d) 四个目标;
1、java简介;历史和地位---跨平台纯面向对象的语言--第三代语言:继承、封装、多态:方法同名,体不同
C++ --- 类函数
.NET---跨语言的平台
SQL--结构化查询语言--第四代语言
Lisp、Prolog人工智能语言---第五代语言
自身发展:95年后变成javaSE
java体系:javase、javaee、javame
特点:面向对象、平台无关、健壮性:无指针、内存的申请与释放(内存分配)
2、工作原理
I java虚拟机
Java虚拟机(JVM)是以 字节码 为机器指令的系统,编译虚拟机的指令集与编译微处理器的指令集非常类似。
Java虚拟机包括一套字节码指令集、一组寄存器、一个栈、一个垃圾回收堆和一个存储方法域。------堆,栈,本地方法栈,方法区,pc寄存器
.java---.class
Ii 垃圾回收机制(GC);不再使用的内存空间应该回收起来
java 的垃圾回收机制:Java的垃圾回收机制是Java虚拟机提供的能力,用于在空闲时间以不定时的方式动态回收无任何引用的对象占据的内存空间。需要注意的是:垃圾回收回收的是无任何引用的对象占据的内存空间而不是对象本身
1.垃圾回收是由虚拟机自动执行,不能人为地干预。
2.系统比较空闲(垃圾回收线程)执行
3.对象不在被引用.对象处于引用的隔离岛状态(隔离引用),对象具备了回收的条件
4.gc()方法,可以建议虚拟机执行垃圾回收,但是不能确定是否会执行回收。
iii、开发环境搭建
tools:JCreator\Eclipse\MyEclipse\Jbuilder\NetBeans
iv、第一个java程序
java源文件;xx.java
基本组成是class,只能有一个public类,命名与其一致
java运行(JVM): 类装载器、字节码校验、解释器
java中只有值传递
三、 数据类型与转换(标示符和关键字、常量与变量、基本数据类型,自动转换,强制转换、转义字符、表达式)
a) 标示符:标示符的格式要求:
i. 定义:java对各种变量、方法和类等要素的命名时使用的字符序列,均须遵守标示符的规则
ii. 规则:
1. 由字母、下划线_、美元符$、数字组成
2. 开头不能是数字
3. 大小写敏感,长度无限制(区别C)
4. 类名首字母一般要大写,方法名一般要小写,并且遵循骆驼命名规则,如:ActiveDemo
b) 关键字
i. 定义:java中一些赋以特定的含义,用作专门用途的字符串
ii. 所有关键字都必须小写
iii. 常用的关键字用
1. 用于数据类型的:int、long、short、String、byte、char、float、double、boolean
2. 用于流程控制的:if、else、for、switch、case、do、while、break、continue
3. 访问控制符:public、protected、default、private
4. 用于异常的:try、catch、finally、throw、throws
5. 返回类型的:native、super、null、void、return、synchronized(同步)
6. 实例:instanceof、this、new
7. 面向对象:class、extends、interface、abstract、final、implements、import、package、static
8. goto和const用来破坏程序入口,也是关键字
c) 常量与变量
i. 常量:(public static final 常量名;)
1. 定义:始终不变的值,可以是数值、字符、字符串
2. 规则:习惯上命名时要大写
ii. 变量:(type varName [=value];)
1. 注意:局部变量使用前必须先初始化不然编译失败!
iii. 调用格式:
1. 调用同文件中的其他类的变/常量格式为:对象.变量
2. 同类中调用其它函数的实例变/常量格式为:new 对象().变量名
3. 同类中调用其它函数的类变/常量格式为: 类名.变量名
d) 数据类型
i. 基本数据类型:byte、short、int、long、char、float、double、boolean
1. 默认值(范围是-2^(n-1)∽2^(n-1)-1)
a) Byte//1、short//2、int//4、long//8------默认值为0
b) char //2--------字符0-----范围是0~65535---unicode编码
c) float//4、double//8--------0.0
d) Boolean//2---------------false
ii. 引用数据类型:数组、类、接口
e) 自动转换(隐式转换)(由小转大)
i. 定义:自动类型转换,也称隐式类型转换,是指不需要书写代码,由系统自动完成的类型转换
ii. 转换规则:byteshort(char)intlongfloatdouble
iii. 示例代码:
1. int i = 4;
2. float n = i;
f) 强制转换(由大转小)
i. 转换规则:double→float→long→int→short(char)→byte
ii. 格式:(转换到的类型)需要转换的数值
iii. 示例代码:
1. double d = 3.10;
2. int n = (int)d;
iv. 注意:强制转换通常都会导致精度的损失
g) 转义字符
i. \b退格
ii. \n换行
iii. \r回车
iv. \’单引号
v. \”双引号
vi. \\反斜杠
h) 运算符------表达式
i. 定义:表达式是由数字、算符、数字分组符号(括号)、自由变量和约束变量等以能求得数值的有意义排列方法所得的组合。约束变量在表达式中已被指定数值,而自由变量则可以在表达式之外另行指定数值
ii. 算术运算符:
1. 单目: ++(自加1)、--(自减1)、+(取正)、-(取负)
2. 双目: + 、- 、* 、/、 %
3. 三目: ?: 如:a>b?a:b
iii. 关系运算符:-------返回结果true/false
1. 等于符号:==
2. 不等于符号:!=
3. 大于符号:>
4. 小于符号:<
5. 大于等于符号:>=
6. 小于等于符号:<=
iv. 逻辑运算符:------返回结果true/false
1. 与(&&):假短路
2. 或(||):真短路
3. 非(!):
v. 位运算符:-----将原数转化为二进制计算
1. 与(&): 如 1100&1010=1000
2. 或(|): 如 1100|1010=1110
3. 非(!): 如 !1100=0011
4. 异或(^): 如 1100^1010=0110
5. << 带符号左移 ------相当于乘以2
6. >>带符号右移 -------相当于除以2
7. >>> 无号右移
8. 异或的规律:
a) a ^ a = 0
b) a ^ b = b ^ a
c) a ^ b ^ c = a ^ (b ^ c) = (a ^ b) ^ c;
d) d = a ^ b ^ c 可以推出 a = d ^ b ^ c.
e) a ^ b ^ a = b
vi. 赋值运算符:
1. =、+=、-=、*=、/=、%=、&=、^=、|=、<<=、>>=
vii. Intanceof:----归属
1. 定义:为双目运算符,左边操作元是一个对象,右边是一个类。当左边的对象是右边类的对象时,返回true
2. 格式:result = object instanceof class 如:a = b instaceof B;//true
viii. 优先级:(从高到低、从左到右)
1. () []
2. ! +(正) -(负) ~ ++ --
3. * / %
4. +(加) -(减)
5. << >> >>>
6. < <= > >= instanceof
7. == !=
8. &(按位与)
9. ^(位异或)
10. |(位非)
11. &&
12. ||
13. ?:
14. = += -= *= /= %= &= |= ^= ~= <<= >>=>>>=
四、 流程控制语句(分支、循环)
a) If…else: 例1.1:
i. If(a>b){
ii. System.out.println(a);
iii. }else if(b>c){
iv. System.out.println(b);
v. }else{
vi. System.out.println(b);
vii. }
b) 分支:(switch)
i. 格式:switch(条件语句){
case :
case :
…..
default :
}
ii. 例1.2:switch(month){
case 1:System.out.println(“spring”);break;
case 1:System.out.println(“spring”);break;
case 1:System.out.println(“spring”);break;
case 1:System.out.println(“spring”);break;
default: System.out.println(“spring”);break;//一定会执行的语句
}
c) For循环
i. 格式:For(初始化语句;条件语句;控制语句){
循环体;
}
ii. 例1.3:for(int i=1;i<101;i++){
int sum = 0;
sum += i;
}
d) while
i. 格式:while(条件语句){
//初始化语句;
循环体;
//控制语句;
}
ii. 例1.4:int i=1;
while(i<101){
int sum=0;
sum += i;
}
e) Do….while()
i. 格式: do{
循环体;
}while(条件语句);
ii. 例1.5:int i =1;
do{
int sum = 0;
sum += i;
}while(i>101);
f) 增强型for循环----------主要用于打印数组元素
i. 格式:for(e:数组名){
循环体
}
ii. 例1.6:int[] a = new int[10];
for(e:a){
System.out.println(e);
}
五、 方法与递归
a) 方法---函数
i. 定义:一段用来完成特定功能的代码片段
ii. 声明格式:【修饰符】返回类型 方法名(形参列表){
方法体;
}
iii. 语法解释:
1. 形式参数:在方法被调用时用于接收外界输入的数据
2. 实参:调用方法时实际传给方法的数据
3. 返回值:方法在执行完毕后返回给调用它的环境的数据
4. 返回值类型:事先约定的返回值的数据类型,无返回值,必须给出返回类型void
5. return语句中止方法的运行并指定要返回的数据
iv. 调用格式:
1. 静态方法(又称类方法)的调用:类名.方法名(实际参数)
2. 实例方法的调用:对象名.方法名(实际参数)
3. 调用中传递参数时,遵循的规则是:基本数据类型是该数据本身,引用数据类型传递的是对象的引用(地址),不是对象本身----基本数据类型:值传递;引用数据类型:地址传递。
v. 例1:
public class DemoMethod{
public static void main(String[] args){//静态方法(又称类方法)的调用:类名.方法名(实际参数)
show("i am a girl");
//实例方法的调用:对象名.方法名(实际参数)//如何产生对象(Object),格式:new 构造方法()
//和类同名的方法称为构造方法
//什么是构造方法(Constructor)?每个类都有一个和类名相同的构造方法,且自动产生
// new DemoMethod().display();
new DemoMethod().visiable(12,"aaa",3.0f);
}
//静态方法的定义【有关键字static修饰的方法】
public static void show(String s){//自定义方法
System.out.println(s);
}
//实例方法的定义【没有关键字static修饰的方法】
public int display(){System.out.println("welcome to jiangxi");return (85);//返回结果,可以用括弧,也可以不用}
//多个参数的实例方法
public void visiable(int x,String y,float f){System.out.println("=======================");}
}
b) 递归----------必须要有出口
i. 定义:递归用于让一个函数从其内部调用其自身
ii. 特点:
1. 程序代码简练,易于理解但浪费内存
2. 一定要有返回类型
3. 一定有if…….else……且if中有终止条件
六、 类(面向对象技术基础、类的声明与使用、对象的声明与使用、构造方法)
a) 面向对象技术基础
i. 面向对象设计的方法论【OOA(分析)OOD(设计)OOP(编程)Test(测试)部署】
ii. 面向对象(Object Oriented,OO)特点:
1. 对象唯一性:每个对象都有自身唯一的标识,通过这种标识,可以找到相应的对象。在对象的整个生命期中,它的标志都是不改变的,不同的对象不能有相同的标识(地址)。
2. 封装性(抽象性):把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏。
3. 继承性:继承性是子类自动共享父类数据结构和方法的机制,这是类之间的一种关系,java中的类只支持单继承,接口支持多继承
4. 多态性(多形性):多态性是指相同的操作或方法、过程可作用于多种类型的对象上并获得不同的结果。不同的对象,收到同一消息可以产生不同的结果,这种现象称为多态性
5. 总结作用:封装可以隐藏实现细节,使得代码模块化;继承可以扩展已存在的代码模块(类);它们的目的都是为了——代码重用。而多态则是为了实现另一个目的——接口重用!多态的作用,就是为了类在继承和派生的时候,保证使用“家谱”中任一类的实例的某一属性时的正确调用。
iii. 面向对象(OO)基本特征
1. 封装(package)
2. 继承(inheritance)------关联关系
a) 继承(泛化generalize)
i. 实现继承
ii. 可视继承
b) 组合(聚合)
i. 接口继承
3. 多态(Polymorphism)
a) 重写(override)
i. 方法
ii. 接口(interface)
b) 重载(overload)
i. 同名函数
b) 类的声明和使用
i. 声明格式:
【修饰符】class【类名】{
方法体;
}
ii. 例1:
public static class Demo{
System.out.println();
}
c) 对象的声明与使用
i. 格式:类名 对象的引用变量 = new 类名();
ii. 例2:Demo d = new Demo();
d) 类与对象的比较
i. 类就是对象的模板,对象是类的实例
e) 构造方法
i. 定义:定义在类中,用来初始化对象的成员变量的方法,返回的是内存地址
ii. 格式:
1. 【修饰符】方法名(){}
2. 例3:public Demo(){}
iii. 要求:
1. 与类同名;2、没有返回值(无void 的修饰);必须要先创建对象,在对象上进行调用(new)
七、 UML
a) UML定义:(Unified Modeling Language)统一建模语言,一种用于面向对象的软件工程的分析与设计阶段的一种可视化建模语言
b) UML关系(类与类之间的关系):关联对属性,依赖对方法
i. 关联关系:菱形指向整体 has a
1. 关联关系------若在逻辑上A是B的“一部分”(a part of),则不允许B从A派生,而是要用A和其它东西组合出B
2. 聚合(aggregation)---实线空心菱形
3. 组合---整体与部分不可分开,实线实心菱形
ii. 泛化(Generalization)关系(继承):用实线空心三角形指向父类 is a
1. 若在逻辑上B是A的“一种”,并且A的所有功能和属性对B而言都有意义,则允许B继承A的功能和属性
iii. 实现关系(接口):虚线
iv. 依赖(Dependency)关系: A”————>”B(A依赖于B) use a 虚线箭头
c) 修饰符图形
i. + public - private # protected ~ 默认访问
d) 建模图形(9种):
i. 用例图(Use Case Diagram):展示系统外部的各类执行者与系统提供的各种用例之间的关系
ii. 类图(Class Diagram):展示系统中类的静态结构(类是指具有相同属性和行为的对象),类图用来描述系统中各种类之间的静态结构
iii. 对象图(Object Diagram):是类图中的一种实例化图(是对类图的实例化)
iv. 顺序图(时序图)序列图(Sequence Diagram):展示对象之间的一种动态协作关系(一组对象组成,随时间推移对象之间交换消息的过程,突出时间关系)
v. 协作图(合作图)(Collaboration Diagram):从另一个角度展示对象之间的动态协作关系(对象间动态协作关系,突出信息收发关系)
vi. 状态图(Statechart Diagram):描述一类对象具有的所有可能的状态及其转移关系(展示对象所具有的所有可能的状态以及特定事件发生时状态的转移情况)
vii. 活动图(Activity Diagram):展示系统中各种活动的执行流程(各种活动的执行顺序、执行流程)
viii. 构件图(Component Diagram):展示程序代码的物理结构(描述程序代码的组织结构,各种构件之间的依赖关系)
ix. 部署图(Deployment Diagram):展示软件在硬件环境中(特别是在分布式及网络环境中)的配置关系(系统中硬件和软件的物理配置情况和系统体系结构)
八、 自定义类
a) 类的定义:类是具有相同属性和相同操作的对象集合,类是对象的模板,一个类可以产生对个对象,产生单个对象的话就是单例模式,类是对现实世界中实体的抽象,对象是对现实世界中实体的实例
b) 类的组成:字段(成员变量)+方法+初始化块(静态初始化块+对象初始化块)
c) 命名规则:类名的首字母大写;变量名和方法名(构造方法除外)的首字母小写,采用骆驼名命名标识
d) 字段(实例变量+类变量(静态变量))的定义格式:
【修饰符(4p、static、final)】 数据类型 属性名【=默认值】;
e) 方法的定义格式:【修饰符(4p、static、final、abstract)】 返回值 方法名(【参数列表】){ 代码块;}
f) 初始化顺序:静态初始化块类变量,实例变量初始化对象初始化块和成员变量初始化(在程序代码中的先后顺序来定)构造方法
g) JavaBean规范:
i. 必须是公共类,并将其访问属性设置为public,如:public class Stu{}
ii. 必须有一个空的构造方法(public、无参):必须有一个不带参数的公共构造器
iii. 字段(实例变量)要私有化,首字母要小写,用private修饰 如:private int id;
iv. 字段应该通过一组存取方法(getter和setter)来访问,一般是用Eclipse、JBuilder、IDE等工具生成getter和setter方法
v. setter和getter规范:字段首字母小写------如:
1. public class Demo{
a) private String name;
b) public Demo(){}
c) public Demo(){
System.out.println(“不错”);
d) }
e) public void setName(String name){
this.name = name;
f) }
g) public String getName(){
return name;
h) }
}
九、 数组(一维数组、二维数组、排序、Arrays.sort)
a) 一维数组
i. 定义:数组就是相同类型元素的集合
ii. 数组变量是引用类型,栈stack(FILO,自动回收)引用堆heap(new出来的,树形结构,JVM回收)中的数据;
iii. 格式:int[] a = new int[3];
int[] a = {1,2,4};
iv. 使用for循环遍历输出,获得数组长度length,访问元素
For…each: 增强型for循环
for(String i:a){//增强型for循环System.out.println(i);}
//冒泡排序
public class SortTest {
public void sort(int[] args){
System.out.println("排序前 ");
for(int m : args){System.out.print(args[m]+",");}
int time1 = 0,time2 = 0;
for(int i = 0 ; i < args.length-1 ; i++){for(int j = i+1 ; j < args.length ; j++){int temp ;if(args[i] > args[j]){temp = args[j];args[j] = args[i];args[i] = temp;}}}System.out.println();System.out.println("排序后 ");for(int n : args){System.out.print(n+",");}}public static void main(String[] args) {int[] arg = new int[]{2,1,4,5,8,7,6,3,9,0};new SortTest().sort(arg);}
}
b) 二维数组-----实质是一维数组引用另一维数组
i. 声明:Int[][] arr;//4个字节
ii. 创建时必须创建行,初始化就是对每个元素进行初始化,使用增强型for循环
十、 Object类
a) Object类是所有类的超类;
b) 常用方法:HashCode()----哈希值,如:
i. IntegertoHexString(p1.hashCode());//把哈希码的无符号十六进制转换成十进制
c) getClass()//获取运行时的类
d) toString()//返回字符,相当于getClass().getName()+”@”+Integer.toHexString(HashCode());
e) clone()//创建一个与源对象完全相同的对象,但新对相象与源对象不相等
i. 子类重写clone()要求:1、创建一个类A实现cloneable接口;2、重写Object的clone(),调用super.clone()
ii. 代码实现:如
public class Person implements Cloneable{
int as ;
protected Object clone() throws CloneNotSupportedException{Person p = (Person)super.clone();
}
}
public class PersonDemo{public static void main()throws CloneNotSupportedException{Person p = new Person();p.as=11;System.out.println(“Before clone”+p.as);Person p1 = (Person)p1.clone();p1.as=22;System.out.println(“After clone”+p.as);}}
十一、 包装类(Integer)
a) 常用方法:
i. Integer.MAX_VALUE();//获取int的最大值
ii. Integer.MIN_VALUE();//获取int的最小值
iii. toBinaryString()//转二进制
iv. toHexStrng()//转十六进制
十二、 抽象类
a) 抽象类的特点:
i. 抽象方法一定在抽象类中;
ii. 抽象方法和抽象类都必须被abstract关键字修饰;
iii. 抽象类不可以用new创建对象,因为调用抽象方法没意义;
iv. 抽象类中的方法要被使用,必须由子类复写起所有的抽象方法后,建立子类对象调用;
v. 如果子类只覆盖了部分抽象方法,那么子类还是一个抽象类
b) 格式:【访问控制符】class 类名{
属性;
访问控制符 返回类型 方法名(形参列表){
//方法体;【return 返回值】
}
访问控制符 abstract 返回类型 方法名(形参列表);
}
例:package b;
public class AbstractDemo{
public static void main(String[] args){Chinese c = new Chinese();}
}
abstract class Chinese{
public abstract void show();
}
abstract class D{
public void show(){System.out.println("213");}
}
十三、 接口(interface)--------不能实例对象,也就是不能new接口
a) 定义:当抽象类中的方法都是抽象的,那么该类可以通过接口的形式来表示
b) 格式:
1、 接口中常见定义:常量、抽象方法
2、 接口中的成员都有固定修饰符
常量:public static final
方法:public abstract
接口中的成员都是public的
c) 接口不可以建立对象,需要被子类实现时,子类对接口中的抽象方法都覆盖后,才可以实例化,否则子类就是一个抽象类
接口支持多实现implements,但接口不能实现接口,可以继承(多继承)接口
d) 例子
public class InterfaceDemo{
public static void main(String[] args){SubInter si = new SubInter();System.out.println(si.NUM);System.out.println(SubInter.NUM);System.out.println(Inter.NUM);}
}
interface Inter{
public static final int NUM = 3;public abstract void show();
}
class SubInter implements Inter{//实现接口
public void show(){}
}
十四、 单例设计模式
a) 定义:是对同一种问题的固定解决方式,单例就是只创建一个对象
b) 想要保证对象唯一:1、为了避免其他程序过多建立该类对象,先控制其他程序建立该类对象;2、为了让其他程序可以访问,在本类中自定义该对象;3、为方便访问,提供访问方式
c) 使用场景:仅需要创建一个对象时
d) 定义步骤:
1、private 的构造方法
2、private static 的实例对象
3、public static外界访问方法
i. 代码实现:
1. 第一种:饿汉式-----先初始化
private int a;
private A(){};
private static A a = new A();
public static get(){
Return a;
}
2. 第二种:懒汉式----调用时初始化—延时加载
private int a;
private A(){};
private static A a = new A();
public static get(){
if(a==null){a == new A();
}
return a;
}
e) 好处:
i. 控制资源的使用
ii. 控制实例的产生数量
iii. 让多个不相关的两个线程或进程之间实现通信
十五、 package
a) 定义:就是把字段和方法包裹起来,并用一定的修饰符加以修饰从而达到对外信息隐藏,并暴露可以暴露的方法
b) Java.lang.*;--------基础包,默认导入
c) 要求:1、必须放在非注释的第一行;2、包名通常是域名的倒置,包名必须小写,不含关键字,不能以java、javax开头
d) 作用:1、便于管理;封装的需要;防止类名冲突
e) 包的导入用import关键字;
f) 常用包有; java.lang.annotation\java.net\java.nio\java.sql\java.util\javax.sql\
javax.xml\javax.swing
十六、 继承(extends)-----类与类之间是属于关系-----关联关系
a) 实现方式:继承(inheritance)和组合(composition)
i. 继承的实现方式有:实现继承、可视继承----------类与类之间是继承(泛化)关系
1. 实现继承是指使用基类的属性和方法而无需额外编码的能力;
2. 可视继承是指子窗口(类)使用基窗口(类)的外观和实现代码的能力;
ii. 组合(聚合关系):接口继承和纯虚类继承
1. 接口继承是指仅使用属性和方法的名称、但是子类必须提供实现的能力。
b) 初始化顺序:先父类静态初始化块--》子类静态初始化块---》父类的对象初始化块---》父类的构造方法--》子类的对象初始化块---》子类的构造方法,如:
package a;
public class B extends A{
static{System.out.println("-------------4------------");}{System.out.println("-------------5------------");}public B(){System.out.println("-------------6------------");}public static void main(String[] args){B b = new B();new B();}
}
class A{
static{System.out.println("-------------1------------");}{System.out.println("-------------2------------");}public A(){System.out.println("-------------3------------");}
}
十七、 多态(向上转型)
a) 多态的坏处
i. 向上转型后,会丢掉子类的新方法
ii. 向上转型是安全的,但向下转型却是不安全的
iii. 例:
package a;
//向上转型------------打印的类型看右边
//缺点:损失掉了子类新增的方法、属性
public class A extends Super{
public void f(Super s){System.out.println(s);}public static void main(String[] args) {//Super a = new A();//a.A@82764b-----打印出A型变量//System.out.println(a);/*A a = new A();a.f(a);//a.A@82764b-------向上转型*///Super[] s = new Super[](new A(),new Super());//System.out.println(a.length);Super[] s = new Super[]{new A(),new Super()};System.out.println(s.length);Object o = new int[3];int[] b = (int[])o;System.out.println(b.length);//编译出错,损失掉了子类新增的方法、属性}
}
class Super{}
b) 后期绑定
i. 将一个方法调用同一个方法主体关联起来被称为绑定。若在程序执行前绑定,叫前期绑定,java中除了static和final方法,其他所有的方法都是后期
ii. Overload-----前期绑定--------静态绑定------编译阶段
Override-----后期绑定--------动态绑定------运行阶段
例:Super a = new subclass();//向上转型-------overload看左边,override看右边
c) 实现多态的方式
i. 重写override:指子类重新定义父类的方法的做法
ii. 重载(overload):是指允许存在多个同名函数,而这些函数的参数表不同(或许参数个数不同,或许参数类型不同,顺序或许两者都不同)
iii. 协变重写:子类方法可以比父类方法的返回类型更具体(子类的返回类型是父类方法返回类型的子类)
d) 只有普通方法具有多态,final、static、private方法不具备多态性
Field(域成员==字段)不具备多态性-----它们都是前期绑定----同变量的声明类型绑定
c) 设计原则:
1、开闭原则---对扩展开放,对修改封闭,实现关键在于抽象化
2、里氏代换原则---面向基类原则---任何基类可以出现的地方,子类一定可以出现
十八、 String(声明,创建,初始化,操作(比较equals/==,转换,查找,截取,分割,拆分,替换,连接))
a) 在java中使用的是unicode码;字符串的内存空间大小跟它的属性有关,String创建初始化时在JVM中数据流动,
b) 声明创建初始化
i. 格式:String 变量名 = 初始值;
ii. String 变量名 = new String(初始值);
c) 操作:
i. 比较(equals与==)
1. equals比的是内容,==比的是地址,equalsIgnoreCase()---忽略大小写
2. 例1:String d = “123”;
String d1 = new String(“123”);
System.out.println(d.equals(d1)); //true
System.out.println(d==d1);//false
ii. charAt(int index)------返回指定索引处的char值
iii. length()--------返回字符串的长度
iv. 转换
1. toString()------返回本身
2. toLowerCase()---将所有字符串转换为小写
3. toUpperCase()---将所有字符串转换为大写
v. 查找
1. indexOf(String key)------从前查找返回的第一个key的索引
2. indexOf(String key,int formindex)----返回从指定位置开始查找到的第一个key的索引
3. lastIndexOf()---------从后查找返回最后一个key的索引
vi. 截取
1. substring(int bindex,int eindex)----截取源字符串(begin,end)并返回一个新String
vii. 拆分
1. split(String regex)-----根据regex将源字符串进行分割成若干个新字符串
viii. 替换
1. replace(char oldchar,char newchar);
ix. 连接
1. + 或concat连接---在源字符串尾部连接新字符串,返回新字符串
2. “a“+”b”;
x. 创建对象
1. String str1 = "abc";
System.out.println(str1 == "abc");
步骤:
1) 栈中开辟一块空间存放引用str1,
2) String池中开辟一块空间,存放String常量"abc",
3) 引用str1指向池中String常量"abc",
4) str1所指代的地址即常量"abc"所在地址,输出为true
2. String str2 = new String("abc");
System.out.println(str2 == "abc");
步骤:
1) 栈中开辟一块空间存放引用str2,
2) 堆中开辟一块空间存放一个新建的String对象"abc",
3) 引用str2指向堆中的新建的String对象"abc",
4) str2所指代的对象地址为堆中地址,而常量"abc"地址在池中,输出为false
3. String str3 = new String("abc");
System.out.println(str3 == str2);
步骤:
1) 栈中开辟一块空间存放引用str3,
2) 堆中开辟一块新空间存放另外一个(不同于str2所指)新建的String对象,
3) 引用str3指向另外新建的那个String对象
4) str3和str2指向堆中不同的String对象,地址也不相同,输出为false
4. String str4 = "a" + "b";
System.out.println(str4 == "ab");
步骤:
1) 栈中开辟一块空间存放引用str4,
2) 根据编译器合并已知量的优化功能,池中开辟一块空间,存放合并后的String常量"ab",
3) 引用str4指向池中常量"ab",
4) str4所指即池中常量"ab",输出为true
5. final String s = "a";
String str5 = s + "b";
System.out.println(str5 == "ab");
步骤:
同4
6. String s1 = "a";
String s2 = "b";
String str6 = s1 + s2;
System.out.println(str6 == "ab");
步骤:
1) 栈中开辟一块中间存放引用s1,s1指向池中String常量"a",
2) 栈中开辟一块中间存放引用s2,s2指向池中String常量"b",
3) 栈中开辟一块中间存放引用str5,
4) s1 + s2通过StringBuilder的最后一步toString()方法还原一个新的String对象"ab",因此堆中开辟一块空间存放此对象,
5) 引用str6指向堆中(s1 + s2)所还原的新String对象,
6) str6指向的对象在堆中,而常量"ab"在池中,输出为false
7. String str7 = "abc".substring(0, 2);
步骤:
1) 栈中开辟一块空间存放引用str7,
2) substring()方法还原一个新的String对象"ab"(不同于str6所指),堆中开辟一块空间存放此对象,
3) 引用str7指向堆中的新String对象,
8. String str8 = "abc".toUpperCase();
步骤:
1) 栈中开辟一块空间存放引用str6,
2) toUpperCase()方法还原一个新的String对象"ABC",池中并未开辟新的空间存放String常量"ABC",
3) 引用str8指向堆中的新String对象
十九、 this
a) this是只指向当前对象的指针;
b) 使用:
i. 如果用在构造方法中,表示当前构造方法正在初始化的对象,如:
1. Person p = new Person();
2. public Person(int id){
this.id = id;//相当于是p.id = id;
3. }
ii. 如果用在方法中,表示当前正在调用该方法的对象,如:
1. public show(int id){
this.id = id;//相当于是p.id = id;
2. }
------------p.show();
二十、 Static------数据共享
a) Static修饰符可以用于修饰类的成员变量和方法-----只在类加载时加载一次
i. 修饰成员变量时,该变量成为类变量或静态变量,隶属于类,类的所有对象共享同一个静态变量(生命周期长,类加载时确立,保存在方法区中)
ii. 修饰方法时,该方法成为类方法或静态方法,可以直接用类名.方法名()调用,也可以使用创建对象后通过对象引用名.方法()调用
iii. 静态方法不能访问非静态方法:
1. 静态方法也称类方法,它在调用时直接使用类名.方法来调用;非静态方法在调用时必须先创建对象,在对象上调用,格式为:对象名.方法名();
2. 在静态方法被调用时可能没有实例对象,也就无法调用非静态方法
二十一、 区别与联系:
a) break与continue与return
i. continue和break都可以结束本轮循环,但continue结束本轮后继续下一轮循环,break则直接跳出循环
ii. break可以用在多重循环中用来跳出离它最近的循环,也可以用在多分支语句swtich中用来跳出循环
iii. continue只能用在循环语句中,用于结束本轮循环,执行下一次循环;
iv. continue与break之后的语句都不执行
v. return是终止方法并返回数据,在方法体内return后的语句都不执行
b) 类变量(static)、实例变量、局部变量
i. 定义:类变量和实例变量定义在类中方法外,局部变量定义在方法内、形参、代码块中
ii. 修饰符:类变量必须要用static修饰,实例变量不用static修饰,类变量和实例变量可以不赋值,局部变量必须要先初始化
iii. 使用:类变量调用格式为:类名.变量名;实例变量调用时必须要先创建实例对象,在该对象上调用(对象.变量名);局部变量可以直接使用
iv. 加载:类变量(栈中)在类加载时加载,类结束时结束;实例变量(堆中)在对象调用时加载,调用结束时结束;局部变量(栈中)在方法开始调用时开始,方法结束时结束
c) this与super
i. 操作属性--------this.属性:表示调用本类中的属性,如果本类中的属性不存在,则从父类开始查找;super.属性:表示调用父类中的属性
ii. 操作方法--------this.方法():表示调用本类中的方法,如果本类中的方法不存在,则从父类开始查找;super.方法():表示调用父类中的方法;
iii. 调用构造方法----this();调用本类中的其他构造方法,super():表示调用父类的构造方法
iv. 查找范围---------this先从子类查找,如果没有从父类查找,super不查子类直接查父类;
v. 特殊:this可以表示当前对象
d) String与StringBuffer、StringBuilder
i. String是不可变的对象,每次对String类型进行改变都相当于产生了一个新的对象,StringBuffer是可变长度的字符序列,修改后不会产生新对象
ii. StringBuffer的实质是它有容量这个属性,默认容量为16,当初始化长度大于16时,其容量为初始化长度的2倍。
iii. String操作字符的方法有”+”、concat;StringBuffer操作字符的方法有insert、append、delete(开始int,endint)
iv. 初始化格式:
1. String st = “234”; String s = new String();
2. StringBuffer sb = new StringBuffer();
v. StringBuffer与StringBuilder都是可变长度的字符序列,在多线程中,前者是安全的,后者是不安全的
e) equals与==
i. 如果是基本类型比较,那么只能用==来比较,不能用equals;
ii. 对于基本类型的包装类型,比如Boolean、Character、Byte、Short、Integer、Long、Float、Double等的引用变量,==是比较地址的,而equals是比较内容的;
iii. 在String或重写equals方法的类中:equals是比内容,==是比地址
iv. 在其他类中没有重写equals方法时,equals与==用法相同,都是比地址
f) 重载与重写
i. 重载与重写都是类的多态表现形式,重载是一个类的多态表现形式,重写是子类继承父类的多态表现形式,重载与重写都是针对方法;
ii. 重载要求同名不同参数列表(类型、个数、顺序),与返回类型无关,重写要求同名同参数列表(类型、个数、顺序),同返回类型(协同----引用数据类型,是其子类或相同,基本数据类型是相同),访问修饰符大于或等于父类,抛出异常要小于或等于父类(当抛出的异常是RuntimeException时,则都可以编译通过)
iii. 重载可以用在构造方法和普通方法中,重写只能用在普通方法中
g) Integer与int
i. 类型:int是基本数据类型,Integer是引用数据类型;
ii. Integer是对int的包装,属于包装类;
iii. 默认值:int的默认值是0,Integer的默认值是null.
h) 类、抽象类、interface
1、抽象类需要有abstract修饰,类则不需要
2、抽象类中可以有普通方法和抽象方法,但普通类中只能有普通方法
3、 抽象类和普通类都可以继承,但抽象类的子类必须重写其父类的所有抽象方法,而普通类则不要求
4、抽象类不能被实例化,普通类可以被实例化
5、接口是抽象类的抽象,接口中只能有抽象方法和常量,接口支持多继承,不含有构造方法和初始化块
i) final、finally与finalize
i. final用于声明属性方法和类,分别表示:属性不可变,方法不可覆盖,类不可继承
ii. finally是异常处理语句的一部分,表示总是执行
iii. finalize是Object的一个方法,在垃圾收集器执行的时候会调用被回收对象的此方法。
二十二、 不能共存的
a) super()与this():都必须放在方法的非注释第一行
b) final与abstract:一个最终的,一个是抽象的
c) abstract与private
一、内部类(局部内部类、成员内部类、匿名内部类)
1、定义:内部类就是在类的内部定义一个类,它的分类有成员内部类、局部内部类、匿名内部类,
它可以定义在类中方法外,也可以定义在类中方法内,内部类的好处是可以访问外部类的私有成员,但外部类无法访问内部类的私有成员
通过使用内部类可以确保程序的结构清晰和代码精炼
编译后的内部类名称:InnerTest$A.class
2、分类:成员内部类(静态成员内部类)、局部内部类、匿名内部类
a、成员内部类(非静态内部类):与外部类的属性和方法并列,成员内部类可以看作是外部类的实例变量
在内部类中访问实例变量:this.字段;
在内部类中访问外部类的实例变量:外部类名.this.字段
成员内部类中不能有静态字段或方法(final修饰的常量除外),因为Static在加载时就创建,此时内部类可能还没被实例化
在外部类的外部实例化对象:
Foo foo = new Foo();
Koo koo = foo.new Koo();
Foo.Koo koo = new Foo().new Koo();
b、静态内部类
静态内部类可以直接访问外部类的静态成员,不能访问外部类的实例成员,但可以通过外部类的实例(new 对象)来访问
静态内部类里面可以定义静态成员(其他内部类不可以)
静态内部类不可以使用private修饰
静态内部类的对象可以直接生成
Foo.Koo koo = new Foo().new Koo();
c、局部内部类
在方法中定义的内部类称为局部内部类,类似局部变量,不可以加修饰符public、protected、private,其范围为定义它的代码块
可以访问外部类的所有成员,还可以访问所在方法中的final修饰的参数和变量,但不能访问方法体中的局部变量
d、匿名内部类
匿名内部类没有类名,它必须继承一个类或者实现一个接口,并且不能显示的extends或implements关键字
匿名内部类不能有构造方法,因为它没有类名。可以通过new<父类名>的方法创建实例对象,匿名类的创建与定义同时进行
匿名内部类只能一次性的创建其对象
匿名内部类既可以在方法体中,也可以在参数列表中
注意:匿名内部类一定是在new的后面隐含实现一个接口或继承一个类,匿名内部类不是抽象类
匿名内部类必须实现他的父类抽象接口或接口里的所有的抽象方法
new 父类的构造器(实参列表)|实现接口(){
//类体
}
new Object(){
}
3、内部类的访问规则:内部类可以直接访问外部类中的成员,包括私有
最近的外部类要访问内部类必须建立内部类对象new Inner().fumction()来访问内部类中的成员
如: Outer.Inner in = new Outer().new Inner();
in.function();
4、使用:当描述事物时,事物的内部还有事物,该事物用内部类来描述,因为内部事物在使用外部事物的内容。
内部类定义在局部时,不能使用成员修饰符、static修饰,使用时需要new—
可以直接访问外部类中的成员,但不可访问它所在的局部中的变量,只能访问被final修饰的局部变量
5、代码分析:例1:----分类
public class Demo2 {
class B{//成员内部类------Demo2$B.class
}
static class A{//静态成员内部类------Demo2$A.class
}
void show(){
class C{//局部内部类-------Demo2$1C.class
}
}
public static void main(String[] args) {
class C{//局部内部类----Demo2$2C.class
}
System.out.println();
}
}
例2:-----匿名内部类
1、 匿名内部类其实就是内部类的简写格式
2、 定义前题必须继承一个类或实现一个接口
3、 匿名内部类的格式: new 父类或接口(){定义子类的内容}
4、 匿名内部类定义的方法最好不要超过三个
public class Test{
public static void main(String[] agrs){
Test t=new Test(); //new了 一个Test对象
t.te(new A(){ //调用实例方法并且声明一个匿名内部类类作为一个参数传入
public void as(){
System.out.println("我是实现了接口A的匿名类");
}
}
);
}
void te(A a){ //实例方法
a.as();
}
}
interface A{ //声明了一个接口类
void as(); //抽象方法
}
例3:
class A{
void as(){
System.out.println("我是内部类A");
}
}
class B{
void bs(){
System.out.println("我是内部类B");
}
}
public class MultipleExtends {
private class C extends A{}
private class D extends B{}
public static void main(String[] args) {
MultipleExtends m=new MultipleExtends(); //声明一个外部类的对象
MultipleExtends.C c=m.new C(); //让外部类对象持有一个
MultipleExtends.D d=m.new D();//内部类对象的引用
c.as();
d.bs();
}
}
例4:-----内部类是可以被私有的
public class MemberClass {
private int i=10; //定义一个私有字段
private static int j=20;
public static void main(String[] args) {
MemberClass mc=new MemberClass();//new 一个外部类的对象
A a=mc.new A();//A a=new MemberClass().new A();//new 一个内部类的对象
a.as();//调用内部类的实例方法
}
private class A{
//static int j=6;
//int i=5; //定义一个内部类的实例字段
void as(){ //定义一个内部类的实例方法
System.out.println("这里是内部类A");
System.out.println("调用外部类私有实例字段i:"+i);
System.out.print("调用外部类私有静态字段j:"+j);
}
}
}
//---------- java ----------
//这里是内部类A
//调用外部类私有实例字段i:10
//调用外部类私有静态字段j:20
例5:----静态内部类
public class StaticClass {
private static int i=10; //定义一个私有静态字段
//private int j=7;
public static void main(String[] args) {
StaticClass sc=new StaticClass();//new 一个外部类的对象
A a=new StaticClass.A(); //new 一个静态内部类
a.as(); //调用静态内部类的实例方法
A.at //调用静态内部类的静态方法
}
static class A{
int i=5;
static at(){ //定义静态内部类的静态方法
System.out.println("这里是静态内部类的静态方法");
}
void as(){ //定义静态内部类的实例方法
System.out.println("这里是内部类A");
System.out.print("调用外部类私有静态字段i:"+i);
}
}
}
例6:------局部内部类
public class InteriorClass {
private int i=5;
public static void main(String[] args) {
InteriorClass ic=new InteriorClass(); //new 一个对象
ic.as(); //调用实例方法
// B b=ic.new B();
}
void as(){
final int y=5; //常量
int u=1; //局部变量
class B{
void bs(){
System.out.println("这里是内部类B");
System.out.println("调用i"+i);
System.out.println("常量"+y);
}
}
new B().bs();
}
}
----------------------------------------------------------------------|----------------------------------------------------------------------|
----------------------------------------------------------------------|----------------------------------------------------------------------|
----------------------------------------------------------------------|----------------------------------------------------------------------|
二、异常(try\catch\fainlly\throw\throws)
i、 异常的含义和分类
a)含义:异常是对问题的描述,将问题进行问题的封装
b)分类:java.lang.Object-----Throwable(java中所有错误和异常的超类)-----Error(无法通过代码来处理的错误)
|---------------Exception(可处理的异常,并能恢复运行)
|---RuntimeException(运行时异常)---可以不捕获也可以不处理
|----CheckedException(已检查时异常)----必须捕获或处理不然编译失败---IOException\SQLException
标签(Marker)接口:既无字段又无方法---Cloneable/Serializable/EventListener
Error----如:JVM硬件错误----OutOfMemoryError—内存不足、不断的创建实例、StackOverflowError---递归导致的堆异常
2、异常分类(Throwable)
1、编译时被检测的异常
throws 需要处理
2、编译时不被检测的异常---运行时异常(RuntimeException或其子类)
函数内throw,函数外不需要声明,--------无法处理,需要修改代码
ii、 异常处理
a)RuntimeEception及其子类异常,不需要程序员处理,其后语句不编译
b)非运行时异常必须处理
c)Exeception中有一个特殊的子类异常RuntimeException,如果在方法内抛出该异常,方法上可以不用声明,编译可以通过;如果在方法上声明了该异常,调用者可以不用处理,编译可以通过。之所以不在函数声明,是因为不希望让使用者处理,当异常发生时,希望程序停止,程序员修正程序代码
异常的捕获和处理
第一种格式:
try{
//可能抛出异常的语句
}catch(异常类型 e){
//处理语句1
} catch(异常类型 e){
//处理语句2
}finally{
//一定执行的语句
}
finally只要用于异常处理,修饰异常块,无论异常是否处理都会执行
finally在return、throw前输出,不管return是在try还是catch中
finally定义一定执行的代码,通常用于关闭资源------如:数据库关闭连接
finally块在以下情况将不会被执行:
(1)finally块中发生了异常;
(2)程序所在线程死亡;
(3)在前面的代码中用了System.exit(0);
(4)关闭CPU。
第二种格式:
try{
}finally{
}
第三种格式:
try{
}catch(){
}
iii.在多个catch时只执行一个,自上而下遇到的第一个异常所对应的catch,如果没有对应的catch,则先执
行finally后在抛出,没有finally则直接抛出,定义多个catch可精确地定位异常。如果为子类的异常定
义了特殊的catch块,而父类的异常则放在另外一个catch块中,此时,必须满足以下规则:子类异常的处
理块必须在父类异常处理块的前面,否则会发生编译错误。所以,越特殊的异常越在前面处理,越普遍的
异常越在后面处理。这类似于制订防火墙的规则次序:较特殊的规则在前,较普通的规则在后。
throws--------声明方法抛出异常
1、说明:当不知道在当前代码中如何处理的时候,可以选择用throws将异常交给上层调用者处理
2、基本格式:
类型 方法名(形参列表)throws 异常列表(逗号隔开){
//代码
}
例:
//手工抛出异常实例
public class JavaThrow1{
public static void main(String[] args){
System.out.print(" Now");
try{
System.out.print(" is");
throw new NullPointerException();//直接抛出异常转到catch进行处理
//System.out.println("This will not excute!");//有throw这句执行不到
}catch (NullPointerException e){
System.out.print(" the");
}
System.out.print(" time.\n");
}
}
//自动抛异常
public class ExTest {
public static void main(String[] args){
String s=null;
try{
System.out.println("0");
int i=s.length();//自动抛异常--空指针异常
System.out.println("2");
}finally{
System.out.println("1");
}
}
}
例:--------throws
public class ExceptionTest4{
public static void p() throws ArithmeticException{
//间接抛出异常,自己并未处理,让方法的调用者来处理
int i;
i=4/0;//可能发生异常
System.out.println("8");
}
public static void main(String[] args){
try{
try{
p();//方法的直接调用调用者捕获异常处理
}catch(ArithmeticException e){
System.out.println("Divider is zero !");
}
}catch(RuntimeException e){
System.out.println("4");
}
}
}
v.java异常处理机制
答:程序出现想数组角标越界,空指针等错误时,JAVA就会用异常Throwable
来描述这些错误,Throwable继承了Object类,同时实现了Serializable接口,
根据出现的问题是否可以通过程序来解决。把Throwable分为Error错误和Exception异常,Exception根据编译时是否会被检
测分为运行时异常RuntimeException和已检测异常CheckedException。异常的处理方
式有两种,在发生异常的地方直接使用catch处理,或者将异常抛出给调用者,让调用者来处理。
1、检查性异常------程序正确,但因为外在的环境条件不满足引发。例如:用
户错误及I/O问题----程序试图打开一个并不存在的远程Socket端口。这不是程序
本身的逻辑错误,而很可能是远程机器名字错误(用户拼写错误)。对商用软件系统,
程序开发者必须考虑并处理这个问题。JAVA编译器强制要求处理这类异常,如果不
捕获这类异常,程序将不能被编译。
2、运行期异常------这意味着程序存在bug,如数组越界,0被除,入参不满足规
范.....这类异常需要更改程序来避免,JAVA编译器强制要求处理这类异常。
3、错误------一般很少见,也很难通过程序解决。它可能源于程序的bug,但一般
更可能源于环境问题,如内存耗尽。错误在程序中无须处理,而有运行环境处理。
三、 自定义异常
当jdk内置异常类型不能满足系统需求时,我们需要自定义异常,如:
public class MyExceptionTest {
public static void main(String[] args) {
MyExceptionTest mt = new MyExceptionTest();
mt.manager();
}
public void registe(int num) throws MyException{
if(num<0){
throw new MyException("人数为负数",3);
}
System.out.println(" 登记人数为:"+num);
}
public void manager(){
try{
registe(-100);
}catch (MyException e){
System.out.println("登记类型出错:"+e.getId());
e.printStackTrace();
}
System.out.println(" 操作结束!");
}
}
class MyException extends Exception{
private int id;
public MyException(){}
public MyException(String message,int id){
super(message);//调用父类的getMessage()
//父类中已经定义了getMessage()可以直接使用-----------该方法为Exception继承Throwable的
this.id=id;
}
public int getId(){
return id;
}
}
自定义异常类必须要继承Exception/RuntimeException,如果该异常的发生无法再继续进行运算,就让它继承RuntimeException
继承的原因是为了让该类自定义类具备可抛型,让该类具备操作异常的共性方法
自定义异常:按照JAVA的OO思想,将程序中出现的特有问题进行封装
四、常见异常
IOException--------------------输入输出异常
ClassNotFoundException-------找不到类异常
NumberFormatException---------字符串到数字格式的异常
FileNotfoundException-----------文件找不到异常
NoSuchMethodException---------------请求方法异常
运行时异常:RuntimeException
SecurityException-----------试图违反安全性异常
NullPointerException----没有实例化却调用其属性和方法--------------空指针异常
ArrayIndexOfBoundsException---------数组越界异常
StringIndexOfBoundsException---------字符串越界异常
ArithmeticException--------------算数异常/除数为零异常
NullPointerException-------试图查找null异常
Main方法通常情况下不能把异常抛给JVM
Super a = new subclass();//向上转型----
---overload看左边,override看右边
-----------------------------------多态针对的是方法
异常的好处:1、将问题进行封装
2、将正常流程代码和问题代码进行分离,方便阅读
处理原则:
1、处理方式有:try或者throws
2、调用到抛出异常的功能时,抛出几个处理几个(一个try对应多个catch)
3、多个catch,父类的catch放到最后
4、Catch内,需要定义针对性的处理方式,不要简单的定义printStackTrace输出语句,也不要不写
5、当铺获到的异常,本功能处理不了时,可以继续在catch中抛出
6、 例:
try{
throw new AException();
}catch(AException e){
throw e;
}
7、如果异常在内部被处理(catch),外部则不需要抛出
基本格式:catch用来处理异常,如果该异常为检测时异常时,必须要处理或者抛出
异常继承时,子类只能抛出父类的异常或者该异常的子类/子集异常,也可以不抛出异常
异常的注意事项
1、在子父类覆盖时,
a)子类抛出的异常必须是父类异常的子类或子集
b)如果父类或接口没有异常抛出时,子类覆盖出现异常,只能try不能抛
c)如果父类中是RuntimeException时,子类可以不用抛出异常,反之,子类为RuntimeException异常,父类为其异常的子类或自己都可以编译通过
1、throw 与throws
throw 后跟异常对象(只能有一个),throws后跟异常类(多个时用逗号隔开);
位置:throw用在方法体中,代表手工抛异常,throws用在方法声明上,代表该方法可能发生异常
2、RuntimeException和CheckedException的区别
前者可以不在方法上声明也可以不处理,后者必须要处理或者抛出
----------------------------------------------------------------------|----------------------------------------------------------------------|
----------------------------------------------------------------------|----------------------------------------------------------------------|
----------------------------------------------------------------------|----------------------------------------------------------------------|
三、集合(collection、set、list、map)
一、定义:
集合是Java里面最常用的,也是最重要的一部分。能够用好集合和理解好集合对于做Java程序的开发拥有无比的好处。
容器:用来存储数据,不同的容器集合以不同的格式保存对象,它能够自动的改变这个容器的所能存放的数据数量的大小。这一点上,如果使用数组来存储的话,就显得十分的笨拙。
对于对象集合,必须执行的操作主要以下三种:
? 添加新的对象
? 删除对象
? 查找对象
Java容器类类库的用途是“保存对象”,并将其划分为两个不同的概念:
1) Collection 。 一组对立的元素,通常这些元素都服从某种规则。List必须保持元素特定的顺序,而Set 不能有重复元素。
2) Map 。 一组 成对的“键值对”对象。
? Collection – 对象之间没有指定的顺序,允许重复元素。
? Set – 对象之间没有指定的顺序,不允许重复元素
? List– 对象之间有指定的顺序,允许重复元素,并引入位置下标。
? Map – 接口用于保存关键字(Key)和数值(Value)的集合,集合中的每个对象加入时都提供数值和关键字。Map 接口既不继承 Set 也不继承 Collection。
List、Set、Map共同的实现基础是Object数组
Collection
1.2.1常用方法
Collection 接口用于表示任何对象或元素组。想要尽可能以常规方式处理一组元素时,就使用这一接口。Collection 在前面的大图也可以看出,它是List和Set 的父类。并且它本身也是一个接口。它定义了作为集合所应该拥有的一些方法。如下:
注意:
集合必须只有对象,集合中的元素不能是基本数据类型。
Collection接口支持如添加和除去等基本操作。设法除去一个元素时,如果这个元素存在,除去的仅仅是集合中此元素的一个实例。
? boolean add(Object element)
? boolean remove(Object element)
Collection 接口还支持查询操作:
? int size()
? boolean isEmpty()
? boolean contains(Object element)
? Iterator iterator()
组操作 :Collection 接口支持的其它操作,要么是作用于元素组的任务,要么是同时作用于整个集合的任务。
? boolean containsAll(Collection collection)
? boolean addAll(Collection collection)
? void clear()
? void removeAll(Collection collection)
? void retainAll(Collection collection)
containsAll() 方法允许您查找当前集合是否包含了另一个集合的所有元素,即另一个集合是否是当前集合的子集。其余方法是可选的,因为特定的集合可能不支持集合更改。 addAll() 方法确保另一个集合中的所有元素都被添加到当前的集合中,通常称为并。 clear() 方法从当前集合中除去所有元素。 removeAll() 方法类似于 clear() ,但只除去了元素的一个子集。 retainAll() 方法类似于 removeAll() 方法,不过可能感到它所做的与前面正好相反:它从当前集合中除去不属于另一个集合的元素,即交。
集合类的基本方法的使用:
import java.util.*;
public class CollectionToArray {
public static void main(String[] args) {
Collection collection1=new ArrayList();//创建一个集合对象
collection1.add("000");//添加对象到Collection集合中
collection1.add("111");
collection1.add("222");
System.out.println("集合collection1的大小:"+collection1.size());
System.out.println("集合collection1的内容:"+collection1);
collection1.remove("000");//从集合collection1中移除掉 "000" 这个对象
System.out.println("集合collection1移除 000 后的内容:"+collection1);
System.out.println("集合collection1中是否包含000 :"+collection1.contains("000"));
System.out.println("集合collection1中是否包含111 :"+collection1.contains("111"));
Collection collection2=new ArrayList();
collection2.addAll(collection1);//将collection1 集合中的元素全部都加到collection2中
System.out.println("集合collection2的内容:"+collection2);
collection2.clear();//清空集合 collection1 中的元素
System.out.println("集合collection2是否为空 :"+collection2.isEmpty());
//将集合collection1转化为数组
Object s[]= collection1.toArray();
for(int i=0;i
}
}
}
运行结果为:
集合collection1的大小:3
集合collection1的内容:[000, 111, 222]
集合collection1移除 000 后的内容:[111, 222]
集合collection1中是否包含000 :false
集合collection1中是否包含111 :true
集合collection2的内容:[111, 222]
集合collection2是否为空 :true
111
222
这里需要注意的是,Collection 它仅仅只是一个接口,而真正使用的时候,却是创建该接口的一个实现类。作为集合的接口,它定义了所有属于集合的类所都应该具有的一些方法。
而ArrayList (列表)类是集合类的一种实现方式。
Collection的实现基础是数组,所以有转换为Object数组的方法:
? Object[] toArray()
? Object[] toArray(Object[] a)
其中第二个方法Object[] toArray(Object[] a) 的参数 a 应该是集合中所有存放的对象的类的父类
1.2.2 迭代器(Iterator)
迭代器(Iterator)本身就是一个对象,它的工作就是遍历并选择集合序列中的对象,而客户端的程序员不必知道或关心该序列底层的结构。此外,迭代器通常被称为“轻量级”对象,创建它的代价小。但是,它也有一些限制,例如,某些迭代器只能单向移动。
Collection 接口的 iterator() 方法返回一个 Iterator。Iterator 和Enumeration 接口类似。使用 Iterator 接口方法,可以从头至尾遍历集合,并安全的从底层 Collection 中除去元素。
迭代器的使用:
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
public class IteratorDemo {
public static void main(String[] args) {
Collection collection = new ArrayList();
collection.add("s1");
collection.add("s2");
collection.add("s3");
Iterator iterator = collection.iterator();//得到一个迭代器
while (iterator.hasNext()) {//遍历
Object element = iterator.next();
System.out.println("iterator = " + element);
}
if(collection.isEmpty())
System.out.println("collection is Empty!");
else
System.out.println("collection is not Empty! size="+collection.size());
Iterator iterator2 = collection.iterator();
while (iterator2.hasNext()) {//移除元素
Object element = iterator2.next();
System.out.println("remove: "+element);
iterator2.remove();
}
Iterator iterator3 = collection.iterator();
if (!iterator3.hasNext()) {//察看是否还有元素
System.out.println("还有元素");
}
if(collection.isEmpty())
System.out.println("collection is Empty!");
//使用collection.isEmpty()方法来判断
}
}
程序的运行结果为:
iterator = s1
iterator = s2
iterator = s3
collection is not Empty! size=3
remove: s1
remove: s2
remove: s3
还有元素
collection is Empty!
可以看到,Java的Collection的Iterator 能够用来,:
1)使用方法 iterator() 要求容器返回一个Iterator .第一次调用Iterator 的next() 方法时,它返回集合序列的第一个元素。
2)使用next() 获得集合序列的中的下一个元素。
3)使用hasNext()检查序列中是否元素。
4)使用remove()将迭代器新返回的元素删除。
需要注意的是:方法删除由next方法返回的最后一个元素,在每次调用next时,remove方法只能被调用一次 。
1.3 List
1.3.1概述
Collection接口实际上并没有直接的实现类。而List是容器的一种,表示列表的意思。当我们不知道存储的数据有多少的情况,
我们就可以使用List 来完成存储数据的工作。例如保存一个应用系统当前的在线用户的信息。List的最大的特点就是能够自动
的根据插入的数据量来动态改变容器的大小。
1.3.2 常用方法
List 就是列表的意思,它是Collection 的一种,即继承了 Collection 接口,又定义一个允许重复项的有序集合。该接口不但
能够对列表的一部分进行处理,还添加了面向位置的操作。List 是按对象的进入顺序进行保存对象,而不做排序或编辑操作。它
除了拥有Collection接口的所有的方法外还拥有一些其他的方法。面向位置的操作包括插入某个元素或 Collection 的功能,还
包括获取、除去或更改元素的功能。在 List 中搜索元素可以从列表的头部或尾部开始,如果找到元素,还将报告元素所在的位置。
1、 void add(int index, Object element):添加对象element到位置index上
2、 boolean addAll(int index, Collection collection):在index位置后添加容器collection中所有的元素
3、 Object get(int index) :取出下标为index的位置的元素
4、 int indexOf(Object element) :查找对象element 在List中第一次出现的位置
5、 int lastIndexOf(Object element) :查找对象element 在List中最后出现的位置
6、 Object remove(int index) :删除index位置上的元素
7、 Object set(int index, Object element) :将index位置上的对象替换为element 并返回老的元素。
List(提供基于索引的对成员的随机访问)------ArrayList-----提供快速的基于索引的成员访问,对尾部成员的增加和删除支持较好
成员可为任意Object子类的对象
----------LinkedList-----对列表中任何位置的成员的增加和删除支持较好,但对基于索引的成员访问支持性能较差
成员可为任意Object子类的对象
在“集合框架”中有两种常规的 List 实现:ArrayList 和 LinkedList。使用两种 List 实现的哪一种取决于您特定的需要。如果要
支持随机访问,而不必在除尾部的任何位置插入或除去元素,那么,ArrayList 提供了可选的集合。但如果,您要频繁的从列表的中间
位置添加和除去元素,而只要顺序的访问列表元素,那么,LinkedList 实现更好。
LinkedList 来实现一个简单的队列的例子:
import java.util.*;
public class ListExample {
public static void main(String args[]) {
LinkedList queue = new LinkedList();
queue.addFirst("Bernadine");
queue.addFirst("Elizabeth");
queue.addFirst("Gene");
queue.addFirst("Elizabeth");
queue.addFirst("Clara");
System.out.println(queue);
queue.removeLast();
queue.removeLast();
System.out.println(queue);
}
}
运行程序产生了以下输出。请注意,与 Set 不同的是 List 允许重复。
[Clara, Elizabeth, Gene, Elizabeth, Bernadine]
[Clara, Elizabeth, Gene]
该的程序演示了具体 List 类的使用。第一部分,创建一个由 ArrayList 支持的 List。填充完列表以后,特定条目就得到了。示例
的 LinkedList 部分把 LinkedList 当作一个队列,从队列头部添加东西,从尾部除去。
List 接口不但以位置友好的方式遍历整个列表,还能处理集合的子集:
ListIterator listIterator() :返回一个ListIterator 跌代器,默认开始位置为0
ListIterator listIterator(int startIndex) :返回一个ListIterator 跌代器,开始位置为startIndex
List subList(int fromIndex, int toIndex) :返回一个子列表List ,元素存放为从 fromIndex 到toIndex之前的一个元素。
处理 subList() 时,位于 fromIndex 的元素在子列表中,而位于 toIndex 的元素则不是,提醒这一点很重要。
for-loop :
for (int i=fromIndex; i
}
对子列表的更改(如 add()、remove() 和 set() 调用)对底层 List 也有影响。
我们看一个List的例子:
import java.util.*;
public class ListIteratorTest {
public static void main(String[] args) {
List list = new ArrayList();
list.add("aaa");
list.add("bbb");
list.add("ccc");
list.add("ddd");
System.out.println("下标0开始:"+list.listIterator(0).next());//next()
System.out.println("下标1开始:"+list.listIterator(1).next());
System.out.println("子List 1-3:"+list.subList(1,3));//子列表
ListIterator it = list.listIterator();//默认从下标0开始
//隐式光标属性add操作 ,插入到当前的下标的前面
it.add("sss");
while(it.hasNext()){
System.out.println("next Index="+it.nextIndex()+",Object="+it.next());
}
//set属性
ListIterator it1 = list.listIterator();
it1.next();
it1.set("ooo");
ListIterator it2 = list.listIterator(list.size());//下标
while(it2.hasPrevious()){
System.out.println("previous Index="+it2.previousIndex()+",Object="+it2.previous());
}
}
}
程序的执行结果为:
下标0开始:aaa
下标1开始:bbb
子List 1-3:[bbb, ccc]
next Index=1,Object=aaa
next Index=2,Object=bbb
next Index=3,Object=ccc
next Index=4,Object=ddd
previous Index=4,Object=ddd
previous Index=3,Object=ccc
previous Index=2,Object=bbb
previous Index=1,Object=aaa
previous Index=0,Object=ooo
我们还需要稍微再解释一下 add() 操作。添加一个元素会导致新元素立刻被添加到隐式光标的前面。因此,添加元素后调用
previous() 会返回新元素,而调用 next() 则不起作用,返回添加操作之前的下一个元素。下标的显示方式,如下图所示:
1.3.3实现原理
ArrayList中主要包含2个属性:
private transient Object elementData[];
private int size;
其中数组::elementData[] 是列表的实现核心属性:数组。 我们使用该数组来进行存放集合中的数据。而我们的初始化参数就
是该数组构建时候的长度,即该数组的length属性就是initialCapacity 参数。
Keys:transient 表示被修饰的属性不是对象持久状态的一部分,不会自动的序列化。
如果要判断一个类的一个实例对象是否等于另外一个对象,那么我们就需要自己覆写Object类的public boolean equals(Object obj)
方法。如果不覆写该方法的话,那么就会调用Object的equals()方法来进行判断。这就相当于比较两个对象的内存应用地址是否相等了。
在集合框架中,不仅仅是List,所有的集合类,如果需要判断里面是否存放了的某个对象,都是调用该对象的equals()方法来进行处理的。
集合的个数用size();数组用length;String用length();
Collection
方法:
增 add();addAll()---------boolean
删 remove();removeAll();------------boolean
clear()-------void
查 Iterator
改 toArray()-----Object 数组
元素数 size()--------------int
List
新增方法:
add(int index, E element)//在指定位置添加---------添加顺序要是连续的
get(int index)//返回指定位置
listIterator(int index)//从指定位置开始迭代
AbstractList
Set
无序的不可重复的Collection
Map
键K不可以重复,值V可以重复
ArrayList------------在查询时快,增删改时慢
例:
import java.util.*;
//注解
//@SuperessWarnings("unchecked")---------
public class Demo{
public static void main(String[] args) {
List
//增加
alist.add("123");
alist.add(new StringBuffer("1s1"));
alist.add(3.4f);
alist.add(3.01d);
alist.add(1,222);//[123, 222, 323]
alist.add("123");//[123, 222, 323, 123]----------可重复
System.out.println(alist);//相当于toString()
System.out.println("长度为:"+alist.size());
System.out.println("------------------------------");
//删除
alist.remove(2);//角标
System.out.println(alist);
//alist.clear();
alist.remove("123");//移除的是第一次出现的
System.out.println(alist);
System.out.println(alist.isEmpty());
System.out.println("------------------------------");
//遍历
//第一种:
for(int i=0;i
if(e instanceof String){//Object inteanceof 类型----判断类型是否是Object的实例
System.out.println(((String)e).length());
}else if(e instanceof Double){
System.out.println(((Double)e).intValue());
}
}
//第二种:
for(Object e:alist){
System.out.println(e);
}
System.out.println("------------------------------");
//List
int size = alist.size();
System.out.println(" size="+size);
boolean flag = alist.isEmpty();//判断是否为空
System.out.println(" flag="+flag);
System.out.println("------------------------------");
//第三种:Iterable-----迭代器输出
//Iterable Iterator
Iterator
while(it.hasNext()){
Object i = it.next();
System.out.println(i);
}
//System.out.println(alist.iterator());
System.out.println("--------------------------------");
//第一种:
for(int i=0;i
}
System.out.println(" ");
System.out.println("--------------------------------");
//第四种:
for(Iterator it2 = alist.iterator();it2.hasNext();){
System.out.println(it2.next());
}
//转换
//alist.toArray();
//System.out.println(alist);
}
}
LinkedList-----------增删改快,查询慢
例:
import java.util.*;
public class Demo1{
public static void main(String[] args) {
Queue
//Queue是单端队列----------单链表
link.add(21);
link.offer(111);//队尾添加========>add
link.poll();//队头删除
System.out.println(link.remove());
link.poll();//为空时返回null==========>remove
System.out.println(link.poll());
link.peek();//访问=========>get
//link.remove();为空时异常
System.out.println(link.size());
System.out.println("-------------------------------------");
Deque
//Deque是双端队列--------双向链表
-------------------------------------------------------------------------------
第一个元素(头部) 最后一个元素(尾部)
抛出异常 特殊值 抛出异常 特殊值
插入 addFirst(e) offerFirst(e) addLast(e) offerLast(e)
移除 removeFirst() pollFirst() removeLast() pollLast()
检查 getFirst() peekFirst() getLast() peekLast()
-------------------------------------------------------------------------------
//add、offer默认在尾部增加
//remove、poll默认从第一个开始删除
dl.add(123);//默认在尾部增加
dl.addFirst("sss");
dl.offerFirst(231);
dl.addLast(2212);
dl.offerLast(654);
System.out.println(dl);
System.out.println("-------------------1---------------");
//dl.removeFirst();
//System.out.println(dl);
//System.out.println("------------------2----------------");
dl.pollLast();
System.out.println(dl);
System.out.println("-----------------3-----------------");
System.out.println(dl.getFirst());
System.out.println("-----------------4-----------------");
dl.peek();
System.out.println(dl);
}
}
注意:所有的集合框架都位于java.util包中,使用前必须导入该包中的类
熟悉并记忆以下接口之间的关系和相关方法
Iterable--------->接口(java.lang)
常见方法1:Iterator
Iterator--------->接口
常见方法1:boolean hasNext()
常见方法2:E next()
Collection------->Iterable-------------->接口
常见方法1:int size()
常见方法2:boolean isEmpty()
常见方法3:void clear()
常见方法4:boolean add(E e)
常见方法5:remove()
List(线性表)----->Collection------->Iterable-------------->接口
常见方法1:add(int index,E e)
常见方法2:remove(int index,E e)
常见方法3:E get(int index)
Queue(队列)----->Collection------->Iterable-------------->接口
常见方法1:offer(E e)
常见方法2:poll()
常见方法3:E peek()
Deque(双端队列)----->Queue----->Collection------->Iterable-------------->接口
常见方法1:offerFirst(E e)和offerLast(E e)
常见方法2:pollFirst()和pollLast
常见方法3:E peekFirst()和peekLast
ArrayList-->AbstractList-->List--->Collection--->Iterator--------->类
LinkedList--->AbstractList-->List--->Collection--->Iterator--------->类
--->Deque---->Queue----->
Vector--->AbstractList-->List--->Collection--->Iterator--------->类
Stack-->Vector--->AbstractList-->List--->Collection--->Iterator--------->类
常见方法1:E pop()
常见方法2:E push(E e)
常见方法3:E peek()
常见方法4:boolean empty()
stack-----------后进先出---一端
无序的不可重复的(判断重复的标准是hashCode()+equals()),如果重复定义则会覆盖
LinkedSet---------------重复时保留第一个
TreeSet-------------(String)按照ASCll码进行排序
加载因子:加载因子 是哈希表在其容量自动增加之前可以达到多满的一种尺度。当哈希
表中的条目数超出了加载因子与当前容量的乘积时,通过调用 rehash 方法将容量翻倍。
通常,默认加载因子 (.75) 在时间和空间成本上寻 求一种折衷。加载因子过高虽然减少
了空间开销,但同时也增加了查询成本(在大多数 Hashtable类的操作中,包括 get 和
put 操作,都反映了这一点)。在设置初始容量时应该考虑到映射中所需的条目数及其加
载因子,以便最大限度地降低 rehash 操作次数。如果初始容量大于最大条目数除以加载
因子,则不会发生 rehash 操作
List默认容量10,HashSet默认容量16,加载因子0.75;
HashMap 的实例有两个参数影响其性能:初始容量 和加载因子。容量是哈希表中桶的数量,
初始容量只是哈希表在创建时的容量。加载因子 是哈希表在其容量自动增加之前可以达到
多满的一种尺度。当哈希表中的条目数超出了加载因子与当前容量的乘积时,则要对该哈希
表进行 rehash 操作(即重建内部数据结构),从而哈希表将具有大约两倍的桶数。
在比较时可以自定义一个比较方式,此类必须要继承Comparable
return -1|0|1; // <|=|>
}
import java.util.*;
public class HashSetTest{
public static void main(String[] args) {
/*Set
set1.add("sds");
set1.add("2sa");
set1.add("213");
set1.add("213");
System.out.println(set1);//无序
System.out.println("--------------------------------------");
Set
set2.add("sds");
set2.add("213");
set2.add("2sa");
set2.add("213");
System.out.println(set2);//按插入顺序输出
System.out.println("--------------------------------------");
Set
set3.add("sds");
set3.add("213");
set3.add("2sa");
set3.add("213");
System.out.println(set3); //排序
System.out.println("--------------------------------------");
*/
Set
Cat c1=new Cat(2,"red");
Cat c2=new Cat(1,"black");
Cat c3=new Cat(3,"white");
set.add(c1);
set.add(c2);
set.add(c3);
System.out.println(set.toString());
}
}
class Cat implements Comparable
private int age;
private String color;
public Cat(int age,String color){
this.age=age;
this.color=color;
}
public String toString(){
return "{age="+age+" , color="+color+"}";
}
public int compareTo(Cat o){
if(this.age>o.age){
return 1;
}else{
return -1;
}
}
}
//---------- java ----------
//[{age=1 , color=black}, {age=2 , color=red}, {age=3 , color=white}]
LinkedHashSet--->HashSet----->AbstractSet----->Set--->Collection------>Iterable
TreeSet------>AbstractSet----->Set--->Collection------>Iterable
TreeSet------>SortedSet------>Set---->Collection------>Iterable
Map
泛型擦除----------类型擦除
类型擦除指的是通过类型参数合并,将泛型类型实例关联到同一份字节码上。编译器只为泛型类型生成一份字
节码,并将其实例关联到这份字节码上。类型擦除的关键在于从泛型类型中清除类型参数的相关信息,并且再
必要的时候添加类型检查和类型转换的方法。
类型擦除可以简单的理解为将泛型java代码转换为普通java代码,只不过编译器更直接点,将泛型java
代码直接转换成普通java字节码。
类型擦除的主要过程如下:
1.将所有的泛型参数用其最左边界(最顶级的父类型)类型替换。
2.移除所有的类型参数,如:
interface Comparable {
public int compareTo( A that);
}
final class NumericValue implements Comparable
priva te byte value;
public NumericValue (byte value) { this.value = value; }
public byte getValue() { return value; }
public int compareTo( NumericValue t hat) { return this.value - that.value; }
}
-----------------
class Collections {
public static >A max(Collection xs) {
Iterator xi = xs.iterator();
A w = xi.next();
while (xi.hasNext()) {
A x = xi.next();
if (w.compareTo(x) < 0) w = x;
}
return w;
}
}
final class Test {
public static void main (String[ ] args) {
LinkedList
numberList .add(new NumericValue((byte)0));
numberList .add(new NumericValue((byte)1));
NumericValue y = Collections.max( numberList );
}
}
经过类型擦除后的类型为
interface Comparable {
public int compareTo( Object that);
}
final class NumericValue implements Comparable {
priva te byte value;
public NumericValue (byte value) { this.value = value; }
public byte getValue() { return value; }
public int compareTo( NumericValue t hat) { return this.value - that.value; }
public int compareTo(Object that) { return this.compareTo((NumericValue)that); }
}
-------------
class Collections {
public static Comparable max(Collection xs) {
Iterator xi = xs.iterator();
Comparable w = (Comparable) xi.next();
while (xi.hasNext()) {
Comparable x = (Comparable) xi.next();
if (w.compareTo(x) < 0) w = x;
}
return w;
}
}
final class Test {
public static void main (String[ ] args) {
LinkedList numberList = new LinkedList();
numberList .add(new NumericValue((byte)0)); ,
numberList .add(new NumericValue((byte)1));
NumericValue y = (NumericValue) Collections.max( numberList );
}
}
第一个泛型类Comparable 擦除后 A被替换为最左边界Object。Comparable
型参数NumericValue被擦除掉,但是这直 接导致NumericValue没有实现接口Comparable的compareTo(Object that)
方法,于是编译器充当好人,添加了一个桥接方法。
第二个示例中限定了类型参数的边界>A,A必须为Comparable的子类
,按照类型擦除的过程,先讲所有的类型参数 ti换为最左边界Comparable,然后去掉参数类型A,
得到最终的擦除后结果。
Collection 和 Collections的区别。
Collection是个java.util下的接口,它是各种集合结构的父接口。继承与他的接口主要有Set 和List.
Collections是个java.util下的专用静态类,它包含有各种有关集合操作的静态方法。提供一系列静态
方法实现对各种集合的搜索、排序、线程安全化等操作。
Array与Arrays的区别。
1.数组类Array,是Java中最基本的一个存储结构。提供了动态创建和访问 Java 数组的方法。其中的
元素的类型必须相同。效率高,但容量固定且无法动态改变。 它无法判断其中实际存有多少元素,
length只是告诉我们array的容量。
2、Arrays类,此静态类专门用来操作array ,提供搜索、排序、复制等静态方法。equals():比较两个
array是否相等。array拥有相同元素个数,且所有对应元素两两相等。 sort():用来对array进行排序。
binarySearch():在排好序的array中寻找元素。
collections
例:
import java.util.*;
public class CollectionsDemo {
public static void main(String[] args) {
List
sl.add("jhn");
sl.add("ncgcxs");
sl.add("rgd");
sl.add("ceaz");
sl.add("vfe");
sl.add("byt");
sl.add("fe");
Collections.sort(sl);
System.out.println(sl);
//Collections.binarySearch(1);
//Collections.copy(sl);
System.out.println(Collections.max(sl));//max
System.out.println(Collections.min(sl));//min
Collections.reverse(sl);//反转
System.out.println(sl);
Collections.shuffle(sl);//打散
System.out.println(sl);
}
HashMap遍历的两种方式
第一种:
Map map = new HashMap();
Iterator iter = map.entrySet().iterator();
while (iter.hasNext()) {
Map.Entry entry = (Map.Entry) iter.next();
Object key = entry.getKey();
Object val = entry.getValue();
}
效率高,以后一定要使用此种方式!
第二种:
Map map = new HashMap();
Iterator iter = map.keySet().iterator();
while (iter.hasNext()) {
Object key = iter.next();
Object val = map.get(key);
}
效率低,以后尽量少使用!
HashMap 与 TreeMap的区别
集合框架”提供两种常规的Map实现:HashMap和TreeMap (TreeMap实现SortedMap接口)。在Map
中插入、删除和定位元素,HashMap 是最好的选择。但如果您要按自然顺序或自定义顺序遍历键,那
么TreeMap会更好。使用HashMap要求添加的键类明确定义了hashCode()和equals()的实现。这个TreeMap
没有调优选项,因为该树总处于平衡状态。
TreeMap
(http://www.cnblogs.com/hzmark/archive/2013/01/02/TreeMap-Base.html)
Java 集合系列目录(Category)
(http://www.cnblogs.com/skywang12345/p/3323085.html)
----------------------------------------------------------------------|----------------------------------------------------------------------|
----------------------------------------------------------------------|----------------------------------------------------------------------|
----------------------------------------------------------------------|----------------------------------------------------------------------|
四、I/O流、File
File--------java.io.File--------文件和目录路径名的抽象表示形式
常用方法:
createNewFile(" ")---------创建文件
delete(" ")
exists()-----------测试是否存在
getName()---------获得文件名
例:
String path = File.separator;//与系统有关的默认名称分隔符
File f = new File("c:"+path+"c.txt");
ystem.out.println(f.createNewFile());
例:import java.io.*;
public class FileDemo {
public static void main(String[] args) throws IOException{
/*
File f = new File("c:\\Users\\Rainlate\\Desktop\\123.txt");//注意\的转义字符
//构建实例不代表创建文件
boolean b =f.createNewFile();//创建文件
f.mkdirs();//创建前不必有父目录
//f.createTempFile(sd,jsp);//使用给定前缀和后缀生成其名称创建空文件
//f.createTempFile(23,txt, null);//使用给定前缀和后缀生成其名称
//boolean d1 = f.delete();//删除此抽象路径名表示的文件或目录。如果此路径名表示一个目录,则该目录必须为空才能删除
System.out.println(f.exists());//是否存在文件
System.out.println(f.getName());//123.txt
String path = File.separator;
File f = new File("c:"+path+"c.txt");
System.out.println(f.createNewFile());
String a = File.separator;
String path="c:"+a+"Users"+a+"Rainlate"+a+"Desktop"+a+"1";
File f = new File(path);
File[] files = new listFiles(f);
for(String file:files){
System.out.println(file);
}
*/
File x= new File("c:\\Users\\Rainlate\\Desktop\\1");
show(x);
}
public static void show(File f){//递归输出源目录下的所有文件
if(f.isDirectory()){//判断是否为目录
File[] files =f.listFiles();
for(int i=0;i
}
}else{
System.out.println(f.getPath());
}
}
}
IO流:
第一,确定方向-----------输入输出是以程序为中心
第二,确定是字节还是字符【若是字符型文本使用字符流,其他使用字节流】
第三,确定是否需要缓冲【autoFlush、Flush】----------缓冲流是用空间换时间
第四,所有操作必须关闭【在finally关闭】
例1;
import java.io.*;
public class FileInputStreamDemo{//文本复制
public static void main(String[] args) {
String a = File.separator;//与系统有关的默认名称分隔符
FileInputStream fin = null;
//FileOutputStream fo = null;
BufferedOutputStream fo = null;
try{
fin = new FileInputStream("C:"+a+"Users"+a+"Rainlate"+a+"Desktop"+a+"123.docx");
byte[] b = new byte[512];//存储读取数据的缓冲区
long start = System.currentTimeMillis();
int size = fin.read(b,0,b.length);
//fo = new FileOutputStream("C:"+a+"Users"+a+"Rainlate"+a+"Desktop"+a+"12.java");
fo = new BufferedOutputStream (new FileOutputStream("C:"+a+"Users"+a+"Rainlate"+a+"Desktop"+a+"12.docx"));
while(size != -1){
fo.write(b,0,size);//文件的实际大小
fo.flush();
size = fin.read(b,0,b.length);
}
long late = System.currentTimeMillis();
System.out.println(late-start);
}catch (FileNotFoundException e){
System.out.println(e.getMessage());
}catch(IOException e){
System.out.println(e.getMessage());
}finally{
try{
fin.close();//关闭输入流
fo.close();//关闭输出流
}catch (IOException e){
System.exit(1);//异常退出
}
}
}
}
例2:
import java.io.*;
public class ObjectSerializable {
public static void main(String[] args) {
Person p = new Person(32,"huhu");
String a = File.separator;
ObjectOutputStream ou =null;//序列化
ObjectInputStream oin = null;//反序列化
try{
ou = new ObjectOutputStream(new FileOutputStream("C:"+a+"Users"+a+"Rainlate"+a+"Desktop"+a+"1.txt"));
ou.writeObject(p);//对象序列化
ou.flush();
//反序列化
oin = new ObjectInputStream(new FileInputStream("C:"+a+"Users"+a+"Rainlate"+a+"Desktop"+a+"1.txt"));
Object obj = oin.readObject();
Person as = (Person)obj;
System.out.println(as);
out.flush();
}catch (FileNotFoundException e){
System.out.println(e.getMessage());
}catch(IOException e){
System.out.println(e.getMessage());
}catch(ClassNotFoundException e){
System.out.println(e.getMessage());
}finally{
try{
out.close();
}catch (IOException e){
System.exit(1);
}
}
}
}
class Person implements Serializable {
private int age;
private String name;
public Person(int age,String name){
this.age=age;
this.name=name;
}
public String toString(){
return "name="+this.name+",age="+this.age;
}
}
序列化的版本号(serialVersionUID=1L)?
作用:就是确保了不同版本之间的兼容性,不仅能够向前兼容,还能够向后兼容,即在版本升级时反序列化仍保持对象的唯一性。
它有两种生成方式:
一个是默认的1L,比如:private static final long serialVersionUID = 1L;
一个是根据类名、接口名、成员方法及属性等来生成一个64位的哈希字段,比如: private static final long serialVersionUID = xxxxL
类图结构
┌BufferedReader
├InputStream──FileReader
├StringReader
┌Reader─┤
│ ├PipedReader
│ ├ByteArrayReader
│ └FileReader──PushbackReader
字符流─┤
│ ┌BufferedWriter
│ ├OutputStreamWriter──FileWriter
│ ├PrinterWriter
└Writer─┼StringWriter
├PipedWriter
├CharArrayWriter
└FileWriter
┌FileInputStream
│ ┌BufferedInputStream
├FilterInputStream ──┼DataInputStream
│ └PushbackInputStream
┌InputStream ─┼ObjectInputStream
│ ├PipedInputStream
│ ├SequenceInputStream
│ ├StringBufferInputStream
│ └ByteArrayInoutStream
字节流─┤
│
│ ┌FileOutputStream
│ │ ┌BufferedOutputStream
│ ├FilterOutputStream ──┼DataOutputStream
└OutputStream ─┤ └PrintStream
├ObjectOutputStream
├PipedOutputStream
IO流------(http://developer.51cto.com/art/201309/410913.htm)
----------------------------------------------------------------------|----------------------------------------------------------------------|
----------------------------------------------------------------------|----------------------------------------------------------------------|
----------------------------------------------------------------------|----------------------------------------------------------------------|
五、html
定义文档类型。
定义 HTML 文档。
定义段落。
定义简单的折行。
定义粗体文本。
不赞成使用。定义文本的字体、尺寸和颜色
定义斜体文本。
定义强调文本。
定义大号文本。
定义语气更为强烈的强调文本。
定义小号文本。
定义上标文本。
定义下标文本。
定义文本的方向。
不赞成使用。定义下划线文本。
定义预格式文本
定义计算机代码文本。
定义打字机文本。
定义键盘文本。
定义文本的变量部分。
定义定义项目。
定义计算机代码样本。
不赞成使用。定义预格式文本。 定义只取首字母的缩写。
定义缩写。
定义文档作者或拥有者的联系信息。
定义块引用。
不赞成使用。定义居中文本。
定义短的引用。
定义引用(citation)。
定义被插入文本。
定义被删除文本。
不赞成使用。定义加删除线的文本。
不赞成使用。定义加删除线的文本。定义框架集的窗口或框架。