-------------------------学习MLDN教学视频-------------------------
1、数据类型:
基本数据类型:
引用数据类型:类、接口、数组
2、Person one=null; //是声明一个对象
one=new Person(); //是实例化对象
3、要是没有实例化
会有异常 NullPointerException
4、实例化
实例化的是指在堆内存对类的属性进行赋值,而方法是在公共内存区中
5、封装性
体现在public与private等等。这样可以保护内容(比如有的属性要被保护),保证了类的完整性。
被封装的属性如果要被访问,则需要缩写setter及getter方法完成。setName getName
6、匿名构造方法
如果定义了有参数的构造方法,就不会自动生成没有参数的构造方法。
7、重载与构造方法重载
参数的个数or参数的类型不同
8、匿名对象
如果一个对象只使用一次,就可以将其定义成匿名对象。
所谓的匿名对象就是少了一个栈中的一个变量,只在堆中实例化了对象。
9、用==进行比较堆内存的中的内容
与栈中变量的比较不同,堆中的内容若是==,表示是指向同一个堆内存。而在栈中只表示他们的值相同,而不管是不是同一个内存空间。
比较他们之间的值是否相等,应该使用String.equals()
10、String两种赋值方式
直接赋值,可以节省内存,因为他是先看堆中看有没有这个字符串。但是用new String()根本不会管,直接开辟堆内存空间了。
所以建议用直接赋值。但是考虑到可能改变了,导致了另一个变量指向的堆的内容变了,但是因为String的对象是不可改变的,所以不用担心。所以不要经常链接-断开的方式,这样会造成很多的垃圾。所以用StringBuffer,这也是专门用来进行处理的。也就是说,如果字符串需要动态改变,就需要用 StringBuffer 类。
11、String常用的api
split()和replaceAll()常常结合正则表达式使用;toCharArray()将字符串变成字符数组;用String可将字符数组变成字符串;charAt()--to find the char of some index;indexOf()找打相应的String的index;trim();startsWith() & endsWith();equalsIgnore
Case()不区分大小写相等;
12、引用传递
类里面的字段可以是自己的本身的类型
13、this也可以用作构造方法中
使用this可以调用其他构造方法,但是此语句必须放在构造方法的首行。thid()、this(arg1)等等必须放在第一个
14、static
在调用static属性的时候,最好使用类名称直接调用。采用“类名称.属性”的形式调用。(static声明属性)
(static声明方法)也可以直接使用类名称调用
15、 java中有几个类型的内存区域
栈内存:可以保存对象的名称
堆内存:保存每个对象的具体属性
全局数据区:保存static类型的属性
全局代码区:保存所有方法的定义
16、内部类加上static就是外部类,可以直接在外部访问。
17、super关键字
先调用父类的构造方法,再调用子类的构造方法。对于子类的构造方法,隐含了一个“super”的语句。有时也将了父类成为超类。在子类构造方法的第一行加上super()是一样的。
18、覆写与super
子类中定义了与父类一样的方法。子类中复写的方法的访问权限不能小于父类中方法的访问权限。要是一定要用父类的方法,就用super关键字,这样就更加明确的说,要从父类中查找,就不从子类查找了。
父类中的方法的访问权限是private,子类中复写的方法的权限是default,这样是不能被复写的。
方法的覆写与重载。重载发生在一个类中,对权限没有要求。覆写放生的继承中,对权限有要求。
在构造方法中,this和super不能同时调用
19、final关键字
final类不能有子类;final方法不能子类被复写;final方法是常量,不可以被修改。
20、abstract
抽象方法只需声明不需实现;抽象类必须被继承,子类如果不是抽象类,必须覆写抽象类中的抽象方法。没有方法体,即是没有{}
21、接口interface
接口的是由全局常量和公共的抽象方法组成。全局常量+抽象方法
public static final
public abstract
22、多态性
方法的重载与覆写;对象的多态性
向上转型;向下转型
向上转型:自动完成。父类中没有的方法子类中有,就没用了。子类中覆写了的父类对象,还是子类的方法体。
向下转型:强制。发生向下转型关系之前必须先发生向上转型关系。子类中有的方法,就全部按照子类的方法。
注意:如果要想产生对象的向下转型,则肯定必须先产生一个向上的转型关系。
23、instanceof
instanceof用于判断一个对象是否是某个类的实例。在对象向下转型之前最好使用instanceof关键字进行验证。
24、注意:一个类永远不要去继承一个已经实现好的类。而只能继承抽象类或实现接口
25、工厂模式 代理设计模式 适配器设计模式
适配器设计,在java的图形界面设计上用得非常多。如果一个接口中的方法过多的话,不需要全部实现的话,就用适配器设计模式。但是在java EE设计中并不常见。
26、Object输出的是利用toString()方法输出的
Object是所有类的父类。只要是引用数据类型都可以用Object进行接受,包括数组。
toString()对象打印时调用,equals()对象比较时调用。
27、包装类 装箱、拆箱
把int包装成一个类,这样就可以以对象的形式操作一个对象了。将基本数据类型变为包装类成为装箱;将包装类的类型变为基本数据类型称为拆箱。
在JDK1.5之后,对与程序本身来说包装类是不能直接进行加减等操作的。但是在JDK1.5之后,可以直接进行加减操作,可以自动装箱、拆箱.甚至可以将字符串变成指定的数据类型。
28、包
包实际上就是一个文件夹。一个*.class文件要保存在一个文件夹之中。在java编译指令中,提供了打包编译命令,在编译的时候加上参数 编译一个文件:javac -d . *.class
29、一个*.class中往往只定义一个public class
30、多线程
继承Thread类;实现Rannable接口
继承Thread必须覆写run()方法;如果想真正启动一个线程,要用start()方法.一旦使用start(),实际上还是调用的run()方法.(run()方法跑起来的线程是一个一个顺序执行的,而start()是抢占式执行的。)
runnable()接口,只定义了一个run()方法。
31、范型是JAVA1.5之后出现的新特性
范型解决数据安全性问题。 [NOTE:范型可以理解为类型先不确定,用到的时候再确定]范型的本质是类型参数化。注意:在范型中,不能用Info<Object>来接受Info<String>类型。
32、java集合(java的类集)
Collection接口。对象数组中包含一组对象,但是对象数组使用的时候存在长度的限制,那么类集是专门解决这种限制的,使用类集可以方便的向数组中增加任意多个数据。
Colletion、List、Set、Map、Iterator、ListIterator、Enumeration、SortedSet、SortedMap、Queue、Map.Entry
重点:List、Set、SortedSet、Queue,全都集成Collection
33、java中一些重要的点
四个:OO、java类集、java IO、JDEC
34、List接口,ArrayList类
List接口要比Collection接口强大很多。添加的方法是用add()、addAll()方法,并且可以定义添加的位置,addAll()方法可以用来增加一个Collection实例化的对象。
删除用remove()方法;size()获得大小;get()获得第几个元素.
截取部分用subList();
LinkedList类,表示一个链表类
35、反射机制
可以通过对象反射求出类的名称。getClass()获得一个对象属于哪一个类.
36、Annotation
元数据特性,也成为注释。
@Override表示方法覆写的正确性;
@Deprecated本身是不建议使用的;
@SuppressWarnings压制警告信息
-------------------------学习vamei的Java教程以及可可西的博客-------------------------
1.包
如果包没有放在当前工作路径下,我们在使用包时,需要通知Java。比如,我们将包放在/home/vamei/javapackage中,这样Human.class位于/home/vamei/javapackage/com/vamei/society/Human.class,而我们的工作路径为/home/vamei。这样,包就无法被找到。一个方法是在使用javac和java时,用-classpath说明包所在的文件夹路径,比如:
$javac -classpath /home/vamei/javapackage:. TestAgain.java
$java -classpath /home/vamei/javapackage:. TestAgain
就是从/home/vamei/javapackage和工作路径(.)中寻找包。Java可以从/home/vamei/javapackage中可以找到Human类,从.中可以找到TestAgain类。
另外也可以设置系统的CLASSPATH环境变量,将上述路径加入到该变量中,而不用每次都键入-classpath选项。
2.方法覆盖(override)
Java中没有virtual关键字!要是参数不是完全一样的,那就是重载,不然就是覆盖。
3.JVM & .class文件
参数 | 抽象类 | 接口 |
默认的方法实现 | 它可以有默认的方法实现 | 接口完全是抽象的。它根本不存在方法的实现 |
实现 | 子类使用extends关键字来继承抽象类。如果子类不是抽象类的话,它需要提供抽象类中所有声明的方法的实现。 | 子类使用关键字implements来实现接口。它需要提供接口中所有声明的方法的实现 |
构造器 | 抽象类可以有构造器 | 接口不能有构造器 |
与正常Java类的区别 | 除了你不能实例化抽象类之外,它和普通Java类没有任何区别 | 接口是完全不同的类型 |
访问修饰符 | 抽象方法可以有public、protected和default这些修饰符 | 接口方法默认修饰符是public。你不可以使用其它修饰符。 |
main方法 | 抽象方法可以有main方法并且我们可以运行它 | 接口没有main方法,因此我们不能运行它。 |
多继承 | 抽象方法可以继承一个类和实现多个接口 | 接口只可以继承一个或多个其它接口 |
速度 | 它比接口速度要快 | 接口是稍微有点慢的,因为它需要时间去寻找在类中实现的方法。 |
添加新方法 | 如果你往抽象类中添加新的方法,你可以给它提供默认的实现。因此你不需要改变你现在的代码。 | 如果你往接口中添加方法,那么你必须改变实现该接口的类。 |
Human aPerson = new Human(160);
a.首先看等号的右侧。new是在内存中为对象开辟空间。具体来说,new是在内存的堆(heap)上为对象开辟空间。这一空间中,保存有对象的数据和方法。b.再看等号的左侧。aPerson指代一个Human对象,被称为对象引用(reference)。实际上,aPerson并不是对象本身,而是类似于一个指向对象的指针。aPerson存在于内存的栈(stack)中。c.当我们用等号赋值时,是将右侧new在堆中创建对象的地址赋予给对象引用。(来自vamei)引用和对象分离;引用指向对象。
源文件的命名规则:如 果在源程序中包含有公共类的定义,则该源文件名必须与该公共类的名字完全一致,字母的大小写都必须一样。这是java语言的一个严格的规定,如果不遵守, 在编译时就会出错。因此,在一个java源程序中至多只能有一个公共类的定义。如果源程序中不包含公共类的定义,则该文件名可以任意取名。如果在一个源程 序中有多个类定义,则在编译时将为每个类生成一个.class文件。
11.Java中的异常
Java中的异常类都继承自Throwable类。一个Throwable类的对象都可以抛出(throw)。所有的异常类必须从Throwable派生,异常分为两大类:一类是unchecked异常(橙色部分):
1、Error类异常由JVM生成并抛出(如:动态链接错误),我们不能在编程层面上解决Error,所以应该直接退出程序。
2、RuntimeException(及其衍生类)是Java程序自身造成的,RuntimeException完全可以通过修正Java程序避免。这类异常,Java编译器不强制要求程序员对其捕获和处理。
另外一类就是checked异常(淡蓝色部分):
Java编译器要求程序员必须捕获或声明所有的这类非运行时异常(如:文件找不到造成的IOException)。
/******************* 自定义异常 *******************/ class ExceptionSelf1Base extends Exception { private String m_strExpInfo; ExceptionSelf1Base(String strVal) { m_strExpInfo = strVal; } public String toString() { return "Exception: " + m_strExpInfo; } } class ExceptionSelf2Base extends Exception { private int m_nExpInfo; ExceptionSelf2Base(int nVal) { m_nExpInfo = nVal; } public String toString() { return "Exception: " + m_nExpInfo; } } class ExceptionSelf1 extends ExceptionSelf1Base { public ExceptionSelf1(String strVal) { super(strVal); } } /******************* 抛出异常 *******************/ class ExceptionTest { // 需要通过throws关键字声明函数内的所有抛出的checked异常 public void throwExp(int nMode) throws ExceptionSelf1,ExceptionSelf1Base,ExceptionSelf2Base { if (nMode < 0) { ExceptionSelf1Base e1 = new ExceptionSelf1Base("nMode < 0"); throw e1; } else if (nMode < 100) { ExceptionSelf2Base e2 = new ExceptionSelf2Base(100); throw e2; } ExceptionSelf1 e = new ExceptionSelf1("nMode >= 100"); throw e; } } /******************* 异常处理 *******************/ public class AppMain { public static void main(String[] args) { ExceptionTest expTest = new ExceptionTest(); try { expTest.throwExp(100); } // 捕捉异常时,需要按照特殊到一般的顺序进行捕捉 catch (ExceptionSelf1 e) { } catch (ExceptionSelf1Base e) { } catch (ExceptionSelf2Base e) { } catch (Exception e) { } // finally为非必需的块 // 进入try块后,无论发生还是不发生异常,finally块中的代码都要被执行,提供了统一的出口 finally { } } }
BufferedReader br = new BufferedReader(new FileReader("file.txt")); String line = br.readLine(); while (line != null) { System.out.println(line); line = br.readLine(); } br.close();
打开一个文件的操作。BufferedReader()是一个装饰器(decorator),它接收一个原始的对象,并返回一个经过装饰的、功能更复杂的对象。
13.RTTI
运行时类型识别(RTTI, Run-Time Type Identification)机制。
14.多线程
在JVM的一个进程空间中,一个栈(stack)代表了方法调用的次序。对于多线程来说,进程空间中需要有多个栈,以记录不同线程的调用次序。多个栈互不影响,但所有的线程将共享堆(heap)中的对象。
15.Java容器
16.嵌套类Java annotation/Java标注
语法: @关键字(值)
用于把关键字和值传递给编译器,更精确低控制编译器的动作。
关键字都是随技术、框架、编译器的不同而不同,含义也不同、数量不定。可以由子技术或开发者扩充。
比如@override 说明会重写该方法
import play.data.validation.Constraints.Email; import play.data.validation.Constraints.Required; public class User { @Email public String email; @Required public String password; public String comment; }
@Email的限定就要求输入为"*@*"的形式。@Required则要求输入栏不为空。如果违反这些限定,那么Play将抛出异常。
19.Java的容器
数组,list,set,map
20.java中的值引用
Java函数参数没有指针传递、引用传递,只有值传递。
值类型参数会产生一个值类型副本,引用类型参数会产生一个引用类型副本(注意:引用类型间赋值不会产生新的对象,因此不会触发拷贝构造函数调用)
因此,想通过函数来实现两个数值变量或对象的交换是不行的。
要是想实现两个值通过函数进行交换,通过函数来实现两个数值变量或对象的交换也是有办法的(包裹:将要交换的数值变量或对象包裹到一个数组或类中)。
/***** AppMain.java *****/ public class AppMain { public static void swapIntTrue(int[] a, int[] b) { int c = a[0]; a[0] = b[0]; b[0] = c; } public static void swapIntegerTrue(Integer[] oa, Integer[] ob) { Integer oc = oa[0]; oa[0] = ob[0]; ob[0] = oc; } public static void main(String[] args) { int n1 = 0; int n2 = 1; Integer on1 = new Integer(0); Integer on2 = new Integer(1); int nArray1[] = new int[1]; int nArray2[] = new int[1]; nArray1[0] = n1; nArray2[0] = n2; System.out.println("n1="+n1 + ", n2="+n2);//n1=0, n2=1 swapIntTrue(nArray1, nArray2); n1 = nArray1[0]; n2 = nArray2[0]; System.out.println("n1="+n1 + ", n2="+n2);//n1=1, n2=0 Integer onArray1[] = new Integer[1]; Integer onArray2[] = new Integer[1]; onArray1[0] = on1; onArray2[0] = on2; System.out.println("on1="+on1 + ", on2="+on2);//on1=0, on2=1 swapIntegerTrue(onArray1, onArray2); on1 = onArray1[0]; on2 = onArray2[0]; System.out.println("on1="+on1 + ", on2="+on2);//on1=1, on2=0 } }
21.java的装箱与拆箱
java里面有自动装箱和拆装的概念,是对基本数据类型和其封装类的相互转换的描述。
当基本类型的数据向其封装类转换时,称为自动装箱。反之,称为拆装。下面给你一个例子:
Integer a = new Integer(1); a = a + 1;//自动装箱
int 型的1 竟然可以直接和Integer对象相加? 关于int和integer之间的关系
其实,这就是JVM“自动”先将Integer型的a转化为int型,就是自动拆装
然后,将两个int型号的数据相加
然后装值给转换为Integer的对象,这个就是自动装箱
JAVA从JDK1.5后,开始支持这个特性
22.java中冒号的用法
首先,可以用在三元运算(比如 (a>b)?true:false);
其次,在循环中用来标识跳到哪儿
C1:for(int i=0; i<100; i++) { C2:for(int j=0; j<100; j++) { if (i==50 && j==80) { // 继续C1层循环 continue C1; } } }
再次,可以用作遍历
int[] code = {0,1,2,3,4,5}; // 针对数组、集合、枚举的for循环形式 JDK1.5之后增加 for (int e : code) { }
最后,switch case中可以用
23.java中的StringBuffer和StringBulider
StringBuffer 处理可变字符串(线程安全),不可被继承(final)
StringBuilder 处理可变字符串(线程不安全,拥有更高的性能),不可被继承(final),JDK1.5引入
StringBuffer与StringBuilder在使用上几乎没有区别
StringBuffer sb1 = new StringBuffer("Hello "); sb1.append("World!"); String str1 = sb1.toString(); // Hello World! StringBuilder sb2 = new StringBuilder("Hello "); sb2.append("World!"); String str2 = sb2.toString(); // Hello World!
24.范型
泛型从JDK1.5才引进;经常被称为参数化类型,它能够像方法一样接受不同类型的参数。
泛型中的通配符:
(1) 泛型中可以使用"?"通配符作为参数,表示该泛型可以接受任意类型的数据
(2) 上届通配符:只允许类A或类A的子类作为参数传入;表示方式:泛型类型<? extends A>
(3) 下届通配符:只允许类A或类A的父类作为参数传入;表示方式:泛型类型<? super A>
如果想从一个数据类型里获取数据,使用 ? extends A 通配符
如果想把对象写入一个数据结构里,使用 ? super A 通配符
如果既想存又想取,那就不要用通配符
/***** AppMain.java *****/ import java.util.*; public class AppMain { public static void main(String[] args) { //ArrayList<?> gList1 = new ArrayList<?>();//编译错误,通配符修饰的泛型不能用来直接创建对象 ArrayList<String> gStrList2 = new ArrayList<String>(); gStrList2.add("1"); ArrayList<?> gList2 = gStrList2; Object objVal = gList2.get(0); //通配符修饰的泛型可以读取数据到Object类型 //gList2.add("2"); //编译错误,【?】通配符修饰的泛型不能写入任何类型数据 //ArrayList<? extends Number> geList1 = new ArrayList<? extends Number>();//编译错误,通配符修饰的泛型不能用来直接创建对象 ArrayList<Integer> geIntList2 = new ArrayList<Integer>(); geIntList2.add(1); List<? extends Number> geList2 = geIntList2; Object objVa2 = geList2.get(0); //通配符修饰的泛型可以读取数据到Object类型 Number nVal = geList2.get(0); //【上届通配符】修饰的泛型可以读取数据到Number类型 //geList2.add(new Integer(2)); //编译错误,【上届通配符】修饰的泛型不能写入任何类型数据 //ArrayList<? super Integer> gsList1 = new ArrayList<? super Integer>();//编译错误,通配符修饰的泛型不能用来直接创建对象 ArrayList<Integer> gsIntList2 = new ArrayList<Integer>(); gsIntList2.add(1); List<? super Integer> gsList2 = gsIntList2; Object objVal3 = gsList2.get(0); //通配符修饰的泛型可以读取数据到Object类型 //Integer nVal2 = gsList2.get(0); //编译错误,【下届通配符】修饰的泛型不能读取数据到除Object类型中 gsList2.add(2); //【下届通配符】修饰的泛型可以写入Integer及其父类类型数据 /*** 自定义泛型 ***/ //Gencs<CString,String,String> gen1 = new Gencs<Float,String,String>();//编译错误,参数1必须为Number或其子类 Gencs<Integer,String,String> gen2 = new Gencs<Integer,String,String>(); Gencs<Float,String,String> gen3 = new Gencs<Float,String,String>(); gen3.setX(3.0f); Float fGen3 = gen3.getX(); Object oGen3 = gen3.getX(); //Integer iGen3 = gen3.getX();//编译错误,返回值为Float类型 //gen3.setX(3);//编译错误,必须传入Float类型参数 } } class Gencs<X extends Number, Y, Z> { private X m_x; //static Y m_y; //编译错误,不能用在静态变量中 public X getX() { return m_x; } public void setX(X x) { m_x = x; } public void fun() { //Z z = new Z();//编译错误,不能创建对象 } }
25.集合
注:点框的为接口、虚线框的为抽象类、实线框的为功能类(右下角的Collections为公用工具类,里面含有大量静态成员函数供集合使用)
集合只能容纳对象,不能容纳基本数据类型;元素通过实现Comparable接口、或提供一个实现Comparator接口的比较算法类来定义比较的规则。
List集合是有序集合(放入的顺序与存储的顺序一致),集合中的元素可以重复,访问集合中的元素可以根据元素的索引来访问。
Set集合是无序集合(放入的顺序与存储的顺序不一致),集合中的元素不可以重复,访问集合中的元素只能根据元素本身来访问。
Map集合中保存key-value对形式的元素,其key对象是不允许重复的(换个角度说:key对象的合集就是一个Set集合),访问时只能根据每项元素的key来访问其value;插入时如果key存在,则替换原来的value对象。
对象重复的含义:
(1) 两个对象e1和e2,如果e1.equals(e2)为true,则认为e1和e2重复,否则认为两个对象不重复
(2) 默认两个对象是否相等的equals方法是判断两个对象变量引用值是否指向同一个地址空间,我们可以重写equals方法来自定义重复的含义
ArrayList线程不安全;Vector线程安全(如果是单线程程序,推荐使用ArrayList)
ArrayList通过数组实现,LinkedList通过链表实现(不涉及到插入、删除等操作,推荐使用ArrayList)
与HashSet相比,TreeSet会对容器内的元素进行排序;同理,相比HashMap,TreeMap也会对容器内的元素进行排序
HashMap线程不安全,键与值都可以为null;Hashtable线程安全,键与值不能为null(如果是单线程程序,推荐使用HashMap)
/***** AppMain.java *****/ import java.util.*; public class AppMain { public static void main(String[] args) { /* ArrayList */ List list = new ArrayList(); list.add(new Integer(1)); list.add("2"); list.add(new Short((short)3)); ListIterator iList = list.listIterator(); while(iList.hasNext()) { System.out.println(iList.next()); } /* HashSet */ Set hSet = new HashSet(); hSet.add("1"); hSet.add(new Integer(2)); hSet.add("3"); Iterator iHSet = hSet.iterator(); while(iHSet.hasNext()) { System.out.println(iHSet.next()); } /* TreeSet */ Set tSet = new TreeSet(); tSet.add("1"); //tSet.add(new Integer(2)); //运行时错误,TreeSet会对元素进行排序,因此需要实现插入元素间相互比较的Comparable接口 tSet.add("3"); Iterator iTSet = tSet.iterator(); while(iTSet.hasNext()) { System.out.println(iTSet.next()); } /* HashMap */ HashMap hm = new HashMap(); hm.put(null, 0); hm.put("1", null); hm.put(new Integer(2), "2"); hm.put("3", new Float(3.0f)); Set sHm = hm.keySet(); Iterator iHm = sHm.iterator(); while(iHm.hasNext()) { Object k = iHm.next(); Object v = hm.get(k); System.out.println(k + "=" + v); } /* Hashtable */ Hashtable ht = new Hashtable(); // ht.put(null, 0); //运行时错误 // ht.put("1", null); //运行时错误 ht.put(new Integer(2), "2"); ht.put("3", new Float(3.0f)); Enumeration e = ht.keys(); while(e.hasMoreElements()) { Object k = e.nextElement(); Object v = ht.get(k); System.out.println(k + "=" + v); } /* TreeMap */ TreeMap tm = new TreeMap(); tm.put("1", new Long(1)); tm.put("2", new Double(2.0)); // tm.put(new Integer(3), "3"); //运行时错误,TreeMap会按照Key进行排序,因此Key需要实现插入元素间相互比较的Comparable接口 Set sTm = tm.keySet(); Iterator iTm = sTm.iterator(); while(iTm.hasNext()) { Object k = iTm.next(); Object v = tm.get(k); System.out.println(k + "=" + v); } } }
以上的示例为非泛型实现的集合,现在已不推荐使用了。(由于使用集合中的元素时,必须进行造型操作,效率低;而且造型操作可能在程序运行时出现问题)
泛型实现的集合在定义容器时,同时定义容器中对象的类型,这就使得容器内的元素只能是该对象类型或其子对象类型。
泛型实现的集合拥有与非泛型实现的集合同样的特性,一致的外部接口。(ArrayList LinkedList HashSet TreeSet HashMap TreeMap Hashtable)
/***** AppMain.java *****/ import java.util.*; public class AppMain { public static void main(String[] args) { /* ArrayList */ List<String> list = new ArrayList<String>(); list.add("1"); list.add("2"); list.add("3"); ListIterator<String> iList = list.listIterator(); while(iList.hasNext()) { System.out.println(iList.next()); } /* HashSet */ Set<Integer> hSet = new HashSet<Integer>(); hSet.add(1); hSet.add(new Integer(2)); hSet.add(new Integer(3)); Iterator<Integer> iHSet = hSet.iterator(); while(iHSet.hasNext()) { System.out.println(iHSet.next()); } /* TreeSet */ Set<String> tSet = new TreeSet<String>(); tSet.add("1"); //tSet.add(new Integer(2)); //编译时错误 tSet.add("3"); Iterator<String> iTSet = tSet.iterator(); while(iTSet.hasNext()) { System.out.println(iTSet.next()); } /* HashMap */ HashMap<String, Integer> hm = new HashMap<String, Integer>(); hm.put(null, 0); hm.put("1", null); hm.put("2", new Integer(2)); hm.put("3", new Integer(3)); Set<String> sHm = hm.keySet(); Iterator<String> iHm = sHm.iterator(); while(iHm.hasNext()) { String k = iHm.next(); Integer v = hm.get(k); System.out.println(k + "=" + v); } /* Hashtable */ Hashtable<String, Integer> ht = new Hashtable<String, Integer>(); //ht.put(null, 0); //运行时错误 //ht.put("1", null); //运行时错误 ht.put("2", new Integer(2)); ht.put("3", 3); Enumeration<String> e = ht.keys(); while(e.hasMoreElements()) { String k = e.nextElement(); Integer v = ht.get(k); System.out.println(k + "=" + v); } /* TreeMap */ TreeMap<String, Integer> tm = new TreeMap<String, Integer>(); tm.put("1", 1); tm.put("2", new Integer(2)); // tm.put(new Integer(3), 3); //编译时错误 Set<String> sTm = tm.keySet(); Iterator<String> iTm = sTm.iterator(); while(iTm.hasNext()) { String k = iTm.next(); Integer v = tm.get(k); System.out.println(k + "=" + v); } } }
26.组合与继承
组合的关系是“has a”,比如手电筒has a电池
上面很多来自博客