java vector 泛型_Java学习日记基础篇(九) —— 集合框架,泛型,异常

集合框架

有事我们会需要一个能够动态的调整大小的数组,比如说要添加新员工但是数组已经满了,并且数组的大小是在定义的时候定死的,所以我们就需要一个能够动态调整大小的数组或者用链表解决,而java中提供了这样一组数组,名为集合类。(有事还是需要链表来解决一些问题的)

dd906b7b1bea786efa66e6472841f5a1.png

重要的就是linkedlist,arraylist,vector,hashset,hashmap

从图中可以看出Java的集合类主要有以下几种:

List结构的集合类 —— ArrayList类,LinkedList类,Vector类,Stack类

Map结构的集合类 —— HashMap类,HashTable类

Set结构的集合类 —— HashSet类,Hashtable类

Queue结构的集合 —— Queue接口

List类——列表结构

ArrayList和Vector的区别

同步性:Vector是同步的而ArrayList则是异步的。所以ArrayList是不安全的但是效率高。

数据增长:Vector会增长一倍的原数组的大小,ArrayList会增长原来的50%,所以集合所占的空间要比实际的需求要大

ArrayList类

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

//使用ArrayList类就要引入一个包

import java.util.*;public classtest1 {public static voidmain(String[] args) {//定义一个ArrayList对象

ArrayList al = newArrayList();//显示大小,用ArrayList类提供的size方法

System.out.println("大小是:"+al.size());//向al中加入数据(类型是Object,Java中所有的类都是从Object中集成下来的,这意味着集合中可以放所有类型的类)//创建一个职员

Clerk clerk1 = new Clerk("松江", 50, 1000);

Clerk clerk2= new Clerk("吴用",45,1200);//将clerk1加入到al中

al.add(clerk1);//默认加载到尾部

al.add(clerk2);

System.out.println("大小是:"+al.size());//如何访问al中对象(数据)//访问第一个对象//Clerk temp = al.get(0);//get()返回的对象是object类型的,是clerk类型的父类,所以会报错//强制转换

Clerk temp = (Clerk)al.get(0);

System.out.println("第一个人的名字是:"+temp.getName());//从al中删除一个对象

al.remove(1);

}

}classClerk

{privateString name;publicString getName() {returnname;

}public voidsetName(String name) {this.name =name;

}public intgetAge() {returnage;

}public void setAge(intage) {this.age =age;

}public floatgetSal() {returnsal;

}public void setSal(floatsal) {this.sal =sal;

}private intage;private floatsal;public Clerk(String name,int age,floatsal)

{this.name =name;this.age =age;this.sal =sal;

}

}

添加,遍历和删除对象

用ArrayList来实现一个简单的员工管理系统

LinkedList类

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

import java.util.*;public classtest4 {public static voidmain(String[] args) {//TODO Auto-generated method stub

LinkedList l1 = newLinkedList();

Emp emp1= new Emp("sa01","aa",1.2f);

Emp emp2= new Emp("sa01","bb",1.2f);

l1.addFirst(emp1);//直接往前加,在链表的最前边

l1.addFirst(emp2);for(int i=0;i

{

System.out.println(((Emp)l1.get(i)).getName());

}

l1.remove(0);//删除也是原来的命令

for(int i=0;i

{

System.out.println(((Emp)l1.get(i)).getName());

}

}

}

能够把后添加的数放到前边

Vector类

Stack类

Map结构的集合类

HashMap和Hashtable的区别

历史原因:Hashtable是基于陈旧的Dictonary类的,HashMap是java 1.2引进的Map接口的一个实现

同步性:HashTable是同步的。这个类中的一些方法保证了Hashtable中的对象是线程安全的。而HashMap则是异步的,因此HashMap中的对象并不是线程安全的。因为同步的要求会影响执行的效率,所以如果不需要线程安全的集合那么使用HashMap是一个很好的选择,这样可以避免由于同步带来的不必要的性能开销,从而提高效率

值:HashMap可以让你将空值作为一个表的条目的key或value,但是Hashtable是不能放入空值的

HashMap类

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 public classtest7 {2 public static voidmain(String[] args)3 {4 //创建一个HashMap对象

5 HashMap hm = newHashMap();6 Emp emp1 = new Emp("s001","aaa",12.3f);7 Emp emp2 = new Emp("s002","bbb",12.3f);8 Emp emp3 = new Emp("s003","ccc",2.3f);9

10

11 //将emp放入到hm中12 //以键值对的形式存入的,查询的时候可以通过是否有指定键或值来查找13 //键是key,值是value

14 hm.put("s001", emp1);15 hm.put("s002", emp2);16 }17 }

创建一个HashMap对象

HashMap的对象的键的值是唯一的

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

public classtest7 {public static voidmain(String[] args)

{//创建一个HashMap对象

HashMap hm = newHashMap();

Emp emp1= new Emp("s001","aaa",12.3f);

Emp emp2= new Emp("s002","bbb",12.3f);

Emp emp3= new Emp("s003","ccc",2.3f);//将emp放入到hm中//以键值对的形式存入的,查询的时候可以通过是否有指定键或值来查找//键是key,值是value

hm.put("s001", emp1);

hm.put("s002", emp2);

hm.put("s002", emp3);//emp3会替换掉emp2,不键允许重复//如果你要查找编号是s002的人

if(hm.containsKey("s002"))//有这个键就返回真,没有就返回假

{

System.out.println("有这个员工");//如何取出

Emp emp=(Emp)hm.get("s002");

System.out.print("名字:"+emp.getName());

}else{System.out.println("没有");}

}

}

在HashMap类中查找对象

遍历集合中所有的对象

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

import java.util.*;public classtest7 {public static voidmain(String[] args)

{//创建一个HashMap对象

HashMap hm = newHashMap();

Emp emp1= new Emp("s001","aaa",12.3f);

Emp emp2= new Emp("s002","bbb",12.3f);

Emp emp3= new Emp("s003","ccc",2.3f);//将emp放入到hm中

hm.put("s001", emp1);

hm.put("s002", emp2);

hm.put("s003", emp3);//emp3会替换掉emp2,不键允许重复//遍历HashMap中所有的key和value//用迭代器Iterator

Iterator it =hm.keySet().iterator();//hasNext返回一个boolean

while(it.hasNext())

{//取出key

String key =it.next().toString();//通过key取出value

Emp emp =(Emp)hm.get(key);

System.out.println("名字:"+emp.getName());

}

}

}

遍历集合中的所有对象

注意:取出来的是乱序的,所以这是它的一个缺点

Hashtable类

总结

java的设计者给我们提供了这些集合类,在后面编程中式相当有用的,具体什么时候用什么集合,要根据我们刚才分析的集合一同来选取。

如果要求线程安全,使用Vector、Hashtable

如果不要求线程安全,应使用ArrayList,LinkedList,HashMap

如果要求有--键值对,则使用HashMap,Hashtable

如果数据量很大,又要考虑线程安全用Vector

泛型

泛型的本质是参数化类型,也就是说所有操作的数据类型被指定成为一个参数。这种参数类型可以在类,接口和方法的创建中,分别称为泛型类、泛型接口、泛型方法。

Java引入泛型的好处是安全简单。泛型的好处是在编译的时候检查类型安全,并且所有的强制转换都是自动和隐式的,提高代码的重用率。

案例:取出集合中的对象的时候需要进行强制的类型转换,否则会报错

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

import java.util.*;*功能:了解泛型的必要性* 时间:2018.10.26

public classtest4 {public static voidmain(String[] args) {//TODO Auto-generated method stub

ArrayList al = newArrayList();

Dog dog1= newDog();//放入到集合中

al.add(dog1);//取出

Dog temp = (Dog)al.get(0);//要有一个强转类型

}

}classDog

{privateString name;private intage;publicString getName() {returnname;

}public voidsetName(String name) {this.name =name;

}public intgetAge() {returnage;

}public void setAge(intage) {this.age =age;

}

}

泛型

808c5249ba62d3dd9f2361431ad8fb78.png

我们在创建一个猫类,可以看出猫类中属性的数据类型和狗类的完全相同,但是表达的意义却不相同,这会引发一个常见的错误,dog类不能转换成dog类型

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

packageproject1;import java.util.*;*功能:了解泛型的必要性* 时间:2018.10.26

public classtest4 {public static voidmain(String[] args) {//TODO Auto-generated method stub

ArrayList al = newArrayList();

Dog dog1= newDog();//放入到集合中

al.add(dog1);//取出//Dog temp = (Dog)al.get(0);//要有一个强转类型

Cat temp = (Cat)al.get(0); //这样写也不会报错,//但编译的时候会出错--类型转换出错

}

}classDog

{privateString name;private intage;publicString getName() {returnname;

}public voidsetName(String name) {this.name =name;

}public intgetAge() {returnage;

}public void setAge(intage) {this.age =age;

}

}classCat

{privateString color;publicString getColor() {returncolor;

}public voidsetColor(String color) {this.color =color;

}public intgetAge() {returnage;

}public void setAge(intage) {this.age =age;

}private intage;

}

类型转换出错

3b350e0c42223f75a440e81c7741fd37.png

1872eea1421d169d9ba91833219b86a2.png

f1187675f44ebeefb5dd3255f27e11dc.png

用泛型类解决这个问题

8695c40f14bed9316612aa901877889d.png

d1f4b59288d06f6c0c906406304633d9.png

泛型的经典用法——Java中的反射机制

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 public classtest5 {2

3 /**

4 *@paramargs5 */

6 public static voidmain(String[] args) {7 //TODO Auto-generated method stub

8 Gen gen1 = new Gen("aaa");//括号内填写字符串类型

9 gen1.showTypeName();10 Gen gen2 = new Gen(1);//括号内是Integer类型

11 gen2.showTypeName();12

13 //14 Gen gen3 = new Gen(new Bird());//括号内是自己新new的Bird类型

15 gen3.showTypeName();16

17 }18

19 }20

21 //定义一个鸟类

22 classBird23 {24 public voidtestt1()25 {26 System.out.println("aa");27 }28 public void count(int a,intb)29 {30 System.out.println(a+b);31 }32 }33 class Gen //T是自己定义的一个类,传入的是什么类型就是什么类型

34 {35 privateT o;36 //构造函数

37 publicGen(T a)38 {39 o=a;40 }41 //得到T的类型名称

42 public voidshowTypeName()43 {44 System.out.println("类型是:"+o.getClass().getName());45 }46

47 }48

49 结果:50 类型是:java.lang.String51 类型是:java.lang.Integer52 类型是:project1.Bird

初识反射机制

通过反射机制可以拿到类的很多信息

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

importjava.lang.reflect.Method;public classtest5 {/***@paramargs*/

public static voidmain(String[] args) {// Gen gen3 = new Gen(new Bird());//括号内是自己新new的Bird类型

gen3.showTypeName();

}

}//定义一个鸟类

classBird

{public voidtestt1()

{

System.out.println("aa");

}public void count(int a,intb)

{

System.out.println(a+b);

}

}class Gen //T是自己定义的一个类,传入的是什么类型就是什么类型

{privateT o;//构造函数

publicGen(T a)

{

o=a;

}//得到T的类型名称

public voidshowTypeName()

{

System.out.println("类型是:"+o.getClass().getName());//通过反射机制,我们可以得到T这个类型的很多信息(比如得到成员函数名)

Method []m =o.getClass().getDeclaredMethods();//这个method需要导包

for(int i=0;i

{

System.out.println("函数名:"+m[i].getName());

}

}

}

运行结果:

类型是:project1.Bird

函数名:count

函数名:testt1

利用反射机制拿类的信息

泛型的优点

类型安全

向后兼容

层次清晰

性能较高用GJ(Generic in Java泛型Java)编写的代码可以为java编译器和虚拟机带来更多的类型信息,这些信息对java程序做进一步优化提供条件着(以后就明白了)

异常处理

基本概念:当出现程序无法控制的外部环境问题(用户提供的文件不存在,文件内容损坏,网络不可用。。。)时,Java就会用异常对象来描述。

Java中用两种方法处理异常:

1、在发生异常的地方直接处理

2、将异常抛给调用者,让调用者处理

异常分类

检查性异常:java.lang.Exception

运行期异常:java.lang.RuntimeException

错误:java.lang.Error

顶层都是java.lang.Throwable集成而来,检查性异常,运行期异常,错误都是这个类的子孙类。

检查性异常(也叫编译异常):程序正确,但因为外在的环境条件不满足引发。例如:用户错误及I/O问题。这不是程序本身的逻辑错误。对于商用软件系统,程序开发者必须考虑并处理这个问题。Java编译器强制要求处理这类异常,如果不能捕获这类异常,程序将不能被编译。

运行期异常:这意味着程序存在bug,如数组越界,0被除,入参不满足规范等等,这类异常需要更改程序来避免,Java编译器要求强制处理这类异常。

错误:一般很少见,也很难通过程序解决。它可能源于程序的bug,但一般更可能源于环境问题,如内存耗尽,杀毒软件太sd。错误在程序中无需处理,而由运行环境处理。

案例:

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

packageproject1;//要使用打开文件的类,就要引入IO包

import java.io.*;import java.net.*;public classtest6 {public static voidmain(String[] args) {//TODO Auto-generated method stub//检查异常 1.打开一个不存在的文件

FileReader fr = new FileReader("d:\\a.text");//2.连接一个不存在的ip端口

Socket s = new Socket("192.168.1.23" , 78);

}

}

检查性异常

25f242388a54b032483bbe9db58fb625.png

b37a556cdfa49a7a42833344aa7fb4cc.png

运行期异常排错要比检查性异常难得多

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

public classtest7 {public static voidmain(String[] args) {//1.除0操作

int a=4/0;//2.数组越界

int arr[] = {1,2,3};

System.out.println(arr[123]);

}

}

运行期异常

b1268c207325fb224ed92db3c3817d0b.png

5ee38c98ea2041f21457ec603b234164.png

错误

异常的解决方法——捕获异常以及将异常抛出去

捕获异常

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 import java.io.*;2 public classtest8 {3 public static voidmain(String[] args) {4 try{5 FileReader fr=new FileReader("d:\\aa.text");6 }7 catch (Exception e)//Exception是最大的异常

8 {9 //把异常输出出来,易于排错

10 e.printStackTrace();11 }12

13 //最小捕获--有什么异常就捕获什么异常

14 try{15 FileReader fr=new FileReader("d:\\aa.text");16 }17 catch (FileNotFoundException e) //18 {19 //把异常输出出来,易于排错

20 e.printStackTrace();21 }22 }23 }

捕获异常

如果是最小捕获异常的话一次只能捕获一个异常

eb03dd9bbb970cc0aa6db5b5c3b26c5c.png

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

import java.io.*;importjava.net.Socket;public classtest8 {public static voidmain(String[] args) {//最小捕获--有什么异常就捕获什么异常

try{

FileReader fr=new FileReader("d:\\aa.text");

Socket s= new Socket("192.168.1.23",88);//因为上局话出现异常后直接就跳到下面去了,所以这句话不会被执行

}catch(FileNotFoundException e)

{

e.printStackTrace();

}catch(IOException e2)

{

e2.printStackTrace();//但这句话不会执行

}

}

}

解决方法

最大捕获则没有问题

cb6d231c6832dfad58226baa8992deac.png

还可以用getMessage方法输出信息,但是输出的内容简单,不会显示是哪一行出错

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

import java.io.*;importjava.net.Socket;public classtest8 {public static voidmain(String[] args) {//最小捕获--有什么异常就捕获什么异常

try{

FileReader fr=new FileReader("d:\\aa.text");

}catch(FileNotFoundException e)

{//输出错误信息

e.printStackTrace();

System.out.println("message:=" +e.getMessage());//处理方法

}

}

}

没什么价值的信息

finally

他是一个万能保险,经常使用。如果把finally块置放在try...catch...语句之后,finally块的语句一般都会得到执行,它相当于一个万能的保险,即使前面的try块发生异常,而又没有对应的异常的catch块,finally块将马上执行。

以下情况finally块将不会被执行

finally块中发生了异常

程序所在线程死亡

在前面的代码中用了System.exit();   退出系统

关闭cpu

打开文件后,不关闭是无法保存的

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

import java.io.*;importjava.net.Socket;public classtest9 {public static voidmain(String[] args) {

FileReader fr=null;try{

fr=new FileReader("d:\\aa.txt");

Socket s= new Socket("192.168.1.1",78);

}catch(Exception e)

{

e.printStackTrace();

}//此时会出现这样一种情况//d盘中有这个文件,文件被打开了,但是没有这台主机,所以下面的会抛出异常//这就造成了文件会一直打开的状态,文件不关闭是无法进行保存的//这是就需要finally语句,如果没有特殊情况它是一定会执行的

finally{

System.out.println("进入finally");//这个语句块,不管有没有出现异常,都会执行//一般来说,把需要关闭的资源,比如说文件,打开的链接(数据库),内存等等

if(fr!=null) //如果文件不是空,就关闭它

{try{

fr.close();//它还是有个异常,我们把它也try..catch掉

} catch(Exception e2) {//TODO: handle exception

e2.printStackTrace();

}

}

}

}

}

finally的用法

注意:只有没有catch,只有try和finally也是能用的,但是一般没人这么用

抛出异常——将异常抛给调用者

一般不会这么用

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

importjava.io.FileReader;public classtest91 {public static voidmain(String[] args) {//TODO Auto-generated method stub

Father father = newFather();

father.test1();

}

}classFather

{private Son son = null;publicFather()

{

son= newSon();

}public voidtest1()

{

System.out.println("ellie");//son.test2();//此时这个方法会抛出一个异常

try{

son.test2();

}catch(Exception e) {//TODO: handle exception

System.out.println("父亲在处理");

e.printStackTrace();

}

}

}classSon

{public void test2() throws Exception //扔出去

{

FileReader fr= null;//fr = new FileReader("d:\\dd.txt");//不try catch这条语句做处理,程序是无法执行的//如果不想处理它,就把他扔出去

fr = new FileReader("d:\\dd.txt");

}

}

抛出异常

报错信息——提示好几个地方有错的时候,只看最前面的错误就可以了

354301ae4f5367a5419c66f6d1eabfdc.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值