Java基础整理(二)
2016-06-10 09:37
441 查看
流程控制、异常处理和断言。
switch表达式必须是byte、short、int或者char类型,而不是布尔变量。Java的循环语句有for while 和 do..while:while是先判断,do..while是即使是条件表达式为假,循环体至少也执行一次。do..在编制菜单选择时非常有效。for循环的执行过程:【1】执行init部分【2】执行condition部分 真-》执行循环体; 假-》循环终止【3】增加或者减少循环控制变量的值【4】重复执行 【2】。
break和continue关键词:break强行退出循环 continue停止当前循环中剩余的语句,退回循环起点,开始新一轮的条件判断。
Java的异常处理:
【1】Throwable is the base class of all errors and exception.only object is the instance of this class
the object can be throw by jvm or Java .
【2】Error is subclass of Throwable 表示程序本身无法恢复的严重错误,用于指示应用程序的严重问题。
【3】Exception以及其子类是Throwable的一种形式,它指出了应用程序想要捕捉的异常,是程序本身可以处理的异常。
【4】RuntimeException是那些可能在Java JVM虚拟机正常运行期间抛出的异常的超类。
重载方法可以指定所有的已检查的异常,或者一部分。
使用assert assertion是代码中包含的一种布尔型状态,程序员认为这个状态是true,一般来说assert在开发的时候是检查程序安全性的,在发布的时候一般不包含assert。
深入理解面向对象的精髓
对象的产生:一种是原型对象为基础产生新的对象;另一种是以类为基础产生新类型。三种基于类的、基于原型和基于元类的对象模型。面向对象的特征:抽象、继承、封装、多态。
*抽象:抽象是忽略一个主题中与当前目标无关的那些方面,而将目标某个特征进行提炼。抽象并不需要了解全部问题,而只是选择其中的一部分。抽象包括两部分:过程抽象和数据抽象。
*继承:继承是一种联结类的层次模型,他提供了一种明确表述共性的方法,并且允许和鼓励类的方法重用。新类可以从现有类中派生,这个过程称为继承,新类继承了原始类的特性派生类可以从基类继承方法和实例变量,并且可以修改和增加方法,使之适合特殊的需要。
*封装:封装把过程和数据包围起来,对数据的访问只能通过调用已经定义的接口,面向对象始于这个基本概念,即现实世界可以被描绘成为一系列完全自治,封装的对象,这些对象通过一个受保护的接口访问其他对象。
*多态:多态性允许不同类的对象对同一消息做出响应。多态性语言具有灵活、抽象、行为共享、代码共享的有事,可以很好的解决应用程序函数重名问题。
面向对象的几个设计原则:【1】开闭原则,对扩展开放,对修改关闭。【2】 依赖倒转原则,要依赖于抽象,而不能依赖于实现。【3】里氏代换原则,任何基类可以出现的地方,子类一定可以出现。开闭原则的关键步骤是抽象画。而基类和子类的继承关系就是抽象化的具体体香,里氏代换原则是对实现抽象画的具体步骤的规范。【4】合成\聚合服用原则,尽量使用合称聚合,而不是使用继承来实现服用的目的。合称和聚合原则要求用户考虑合成\聚合的关系【5】迪米特原则软件的实体应该尽可能少的与其他实习发生相互作用。模块之间的交互要少,这样的有点是当系统的功能需要修改的时候能够相对容易的做到对修改的关闭。【6】接口隔离原则,应当为客户端体提尽快小的接口,而不要提供大的总接口。也即是使用多个专门的接口比使用单一的接口要好。
类的继承是是一个的关系的确定,聚合和合称 有一个的关系的创建。
在Java中,同一个类中的2个或者2个以上的方法可以拥有同一个名字,只要是他们的参数声明不同即可。这种状况称为方法重载。
方法覆盖的问题:【1】子类的方法名称、参数名和返回类型必须与父类的方法的名称、参数名和返回类型一致【2】子类的方法不能够缩小父类方法的访问权限3】子类方法不能抛出比父类方法更多的异常。子类抛出的异常必须和父类相同或者是父类异常的子类。【4】方法覆盖仅仅是存在于子类和父类【5】父类的静态方法不能被子类覆盖为非静态方法6】子类和父类的静态方法可以重名,以便在子类中隐藏父类的方法。在编译的时候,子类定义的静态方法也必须满足与方法覆盖类似的约束;方法的参数名一致,返回类型一致,不能缩小父类的方法的权限,不能够抛出更多的异常。【7】父类的非静态方法不能够被子类覆盖为静态方法【8】父类的私有方法不能够被子类覆盖【9】父类的抽象方法可以被子类通过两种途径来覆盖:一种是实现抽象方法;另一种是重新声明父类的
RuntimeException异常可以不显示的声明,默认的情况下,都可以抛出RuntimeException异常的。
重载和覆盖的异同点:
*相同【1】都要求方法同名【2】都可以用于抽象方法和非抽象方法
*不同:覆盖要求参数一致,而重载要求参数必须不一致;覆盖要求返回类型必须一直,重载对此不做限制;覆盖只能用于子类覆盖父类方法,重载应用于同一个类中;覆盖对方法的访问权限和异常有特殊要求,重载没有限制;父类的一个方法只能被子类覆盖一次,而一个方法可以重载多次。
GC垃圾回收
Java GC(Garbage Collection,垃圾收集,垃圾回收)机制,是Java开发人员需要深入理解的一部分内容。Java的开发一般不需要专门的编写内存回收和垃圾清理代码,对内存泄漏和溢出的问题,在JVM中存在自动内存管理和垃圾清扫机制。概括地说,该机制对 JVM(Java Virtual Machine)中的内存进行标记,并确定哪些内存需要回收,根据一定 的回收策略,自动的回收内存,永不停息(Nerver Stop)的保证JVM中的内存空间,防止出现内存泄露和溢出问题。Java GC机制主要完成3件事:确定哪些内存需要回收,确定什么时候需要执行GC,如何执行GC。Java 的垃圾回收并不能够保证内存不被耗尽,垃圾回收只是一个低优先级的后台线程,而且跟踪可达或者不可达对象。
初始器的理解.
[1]表达式变量初始器:变量的声明语句中利用表达式型的初始器可以明确规定变量的初始化。
[2]代码快型的静态初始器,不过这种初始化只会在初始化类的时候执行一次。
[3]代码块型的实例初始器:提供了在对象创建期间初始化变量的能力,这种代码块所起的作用和对象构建期间的构造函数一样。
[4]构造对象的初始状态:final类型的变量,当构造一个实例的时候这个变量是必须进行初始化的。
Java初始器的执行顺序是先静态代码块,静态变量,然后是创建对象的时候 代码块 构造函数
DEMO
package ic.lbz.ch07; /** * @author LbZhang * @version 创建时间:2016年5月31日 下午7:13:39 * @description 构造对象的初始状态 */ public class Init { public static void main(String[] args) { B b = new B(); System.out.println("main method: i=" + b.i); } } class A { int i = 20; public A() { System.out.println("classs A cons i=" + i); } { ++i; System.out.println("class A block cons i=" + i); } } class B extends A { int i = 5; B() { this(3); System.out.println("classs B cons i=" + i); } B(int j) { System.out.println("classs B cc cons i=" + j); } { ++i; System.out.println("class B block cons i=" + i); } }
线程
线程和进程的区别:进程和线程是由操作系统所体会的程序运行的基本单元,系统利用该基本单元实现系统对应用的并发型。[1]一个程序至少有一个进程,一个进程至少有一个线程。线程的划分尺度小于进程,使得多线程程序的并发性高。
[2]进程在执行过程中拥有独立的内存单元,而多个线程是共享内存的,从而极大的提高了程序的运行效率。
[3]线程在执行过程中和进程是有区别的。每个独立的线程有一个程序运行的入口、程序顺序执行和程序运行的出口。但是线程不能够独立的执行,必须依存在应用程序中。
[4]从逻辑的角度讲,多线程的意义在于一个应用程序中有多个执行部分可以同时执行。操作系统并没有将线程看作多个独立的应用,来实现进程的调度和管理,以及资源分配。这就是线程和进程的区别。
[5]进程是具有一定独立功能的程序关于某个数据集合上面的一次运行活动,进程是系统进行资源分配和调度的单位。
[6]线程是一个进程的实体,是cpu调度和分派的基本单位,它是比进程更小的能够独立运行的基本单位。线程本上基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(程序计数器、一组寄存器和栈),但是它与同属一个进程的其他线程共享进程拥有的全部资源。
[7]一个线程可以创建和撤销另一个进程,同一个进程中的多个线程可以并发执行。
总结:线程和进程的主要差别在于,它们是不同操作系统资源管理方式。进程有独立的地址空间,一个进程崩溃之后,在保护模式下不会对其他的进程产生影响,而线程只是进程中的一个不同的执行路径。线程有自己的堆栈和执行变量,单线程之间没有单独的地址空间,一个线程的死掉会等于整个进程死掉,所以多进程的程序比多线程的程序健壮,但是在进程进行切换的时候,消耗资源较大,效率差一些。但是对于一些要求同时进行又需要共享某些变量的并发操作,只能用线程,不能用进程。
具有生命的线程状态:创建-》就绪-》运行-》阻塞或者等待、睡眠-》死亡状态
线程同步的方式:
[1]共享变量,要使得多个线程在一个程序中有用,必须有某种方法实现县城建相互通信活共享结果,最简单的方法是使用共享变量。使用同步来确保值从一个线程正确传播到另一个线程,以及防止当一个线程正在更新一些相关的数据项时,另一个线程看到不一致的中间结果。
[2]存在于同一个内存空间中的所有线程,线程与进程中的其他线程共享相同进程上的上下文,包括内存空间。只要访问共享变量,线程就可以方便的交换数据,但是需要确保线程以受控的方式访问共享变量,以免它们互相干扰对方的修改。
[3]受访问的同步,为了确保可以在线程之间可以受控的方式共享数据,Java语言提供了两个关键字:synchronized 和 volatile。
synchronized有一下两个重要含义:
》一次只能有一个线程可以执行代码受保护的部分
》一个线程更改的数据对于其他线程是可见的。
[4]确保共享数据的可见性,同步让用户确保线程看到一致的内存视图。
volatile比同步更简单,只适合用于控制基本变量(整数布尔变量等)的单个实例的访问。当一个变量声明为volatile,任何对该变量的写操作都会绕过高速缓存,直接写入到主内存,而任何对变量的读取也绕过高速缓存,直接读取内存。这表示所有线程在任何时候看到的变量的值都相同。
[5]用锁保护的原子代码块
volatile对于确保每个线程能够看到最想的变量值非常有用,但是实际上经常需要保护代码片段,同步监视器或者锁的概念,以协调对特定代码块的访问。
每个Java 对象都有一个相关的锁,同一时间只能有一个线程持有Java锁。当线程进入synchronized代码块时,线程会阻塞等待,直到锁可以使用。当线程进入就绪状态时,并且获得锁后,将执行代码块,当控制退出受保护的代码块,即达到了代码块末尾或者抛出了没有在synchronized块中捕获的异常时,他就会释放锁。
package ic.lbz.ch08; /** * @author LbZhang * @version 创建时间:2016年6月1日 上午10:27:16 * @description 简单的同步实例 * * 线程同步的方式: * [1]共享变量,要使得多个线程在一个程序中有用,必须有某种方法实现县城建相互通信活共享结果,最简单的方法是使用共享变量。使用同步来确保值从一个线程正确传播到另一个线程, * 以及防止当一个线程正在更新一些相关的数据项时,另一个线程看到不一致的中间结果。 * [2]存在于同一个内存空间中的所有线程,线程与进程中的其他线程共享相同进程上的上下文,包括内存空间。只要访问共享变量,线程就可以方便的交换数据,但是需要确保线程以受控的方式访问共享变量,以免它们互相干扰对方的修改。 * [3]受访问的同步,为了确保可以在线程之间可以受控的方式共享数据,Java语言提供了两个关键字:synchronized 和 volatile。 * synchronized有一下两个重要含义: * 》一次只能有一个线程可以执行代码受保护的部分 * 》一个线程更改的数据对于其他线程是可见的。 * [4]确保共享数据的可见性,同步让用户确保线程看到一致的内存视图。 * volatile比同步更简单,只适合用于控制基本变量(整数布尔变量等)的单个实例的访问。当一个变量声明为volatile,任何对该变量的写操作 * 都会绕过高速缓存,直接写入到主内存,而任何对变量的读取也绕过高速缓存,直接读取内存。这表示所有线程在任何时候看到的变量的值都相同。 * [5]用锁保护的原子代码块 * volatile对于确保每个线程能够看到最想的变量值非常有用,但是实际上经常需要保护代码片段,同步监视器或者锁的概念,以协调对特定代码块的访问。 * 每个Java 对象都有一个相关的锁,同一时间只能有一个线程持有Java锁。当线程进入synchronized代码块时,线程会阻塞等待,直到锁可以使用。当线程进入就绪状态时, * 并且获得锁后,将执行代码块,当控制退出受保护的代码块,即达到了代码块末尾或者抛出了没有在synchronized块中捕获的异常时,他就会释放锁。 * http://blog.csdn.net/aboy123/article/details/38307539 * http://dylanxu.iteye.com/blog/1322066 * */ public class SyncExample { private static Object lockObject = new Object(); private static class Thread1 extends Thread{ int x,y; @Override public void run() { //synchronized(lockObject) { x=y=0; System.out.println(x); } } } private static class Thread2 extends Thread{ int x,y; @Override public void run() { { x=y=1; System.out.println(y); } } } public static void main(String[] args) { new Thread1().run(); new Thread2().run(); } }
面向对象的基础类
IO
File类:File实例表示主机文件系统中的文件。一个文件能够通过一个路径名指定,此路径名可以是一条据对路径名,也可以是一条相对于当前工作目录的相对路径名。路径名必须遵循主机平台的命名约定。File类提供提供了一种抽象的方式,以与机器无关的方式处理文件和路径名的复杂问题。*FileInputStream类:文件输入流,输入流以字节为单位(非unicode)二进制数据与编码无关。
FileReader读取字符的方便类。FileReader类是InputStreamreader类的子类
FileReader和FileInputStream类的区别如下:FileReader是将文件转换为字符流输入,InputStream提供的是字节流的读取,而不是文本的读取。这是Reader类的根本区别。用Reader读取来的是用char数组或者String,使用InputStream读取来的是byte数组。
Reader类以及子类提供的字符流读取char(16位,unicode编码),InputStream极其子类提供字节流读取(byte 八位)。所以FileReader类是将文件按照字符流的方式读取,FileInputStream按照字节流的方式读取文件。InputStreamReader可以将字节流流转换成为字符流,是reader和stream之间的桥梁。最初Java是不支持对文本的文件处理的,为此引入了Reader和Writer两个类。
FileInputStream类似二进制输入输出,IO速度快且效率高,但是他们read()方法读到的是一个字节(二进制数据),很不利于人们的阅读,而FileReader类弥补了这个缺陷,可以以文本的格式输入输出,非常方便。
package ic.lbz.ch09; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.RandomAccessFile; import java.io.Reader; /** * @author LbZhang * @version 创建时间:2016年6月3日 上午8:31:40 * @description 输入输出流的常规类 * * http://blog.csdn.net/yczz/article/details/38761237 * * IO是计算机输入输出的接口。Java的核心类库java.io提供了全面的IO接口,包括文件读写、标准输入输出等。 * Java中IO是以流为基础进行输入输出的 所有的数据被串行化写入输出流,或者从输入流读入。 * 流IO的好处就是简单易用、确定是效率低。 块IO的效率高,但是编程比较复杂。 * * Java的IO模型设计非常优秀,它使用Decorator模式,用户可以动态装配不同功能的Stream,以便获得需要的功能。 * Java的IO体系分为Input * /Output和Reader/Writer两类,区别在于Reader/Writer在读写文本的时候能够自动转换内码。基本上, * 所有的IO类都是配对的。 * * * */ public class IOTest { public static void main(String[] args) throws IOException { System.out.println("------------IO Test-------------"); IOTest.readFilesByBytes(); String fileName = "E:/temp.txt"; //IOTest.readFilesByChars(fileName); //IOTest.readFileByLines(fileName); //System.out.println("Random Access!"); //IOTest.readFileByRandomAccess(fileName); //IOTest.appendMethodA(fileName, "ddddd"); //IOTest.appendMethodB(fileName, "bbbbbbbbbbbbbbbbbbbbb"); } /** * 以字符为单位读取文件,常用于读文本,数字等类型的文件 */ private static void readFilesByChars(String fileName) { File file = new File(fileName); //File file = new File("E:/temp.txt"); Reader reader = null; // try { // System.out.println("以字符为单位读取文件内容,一次读一个字节:"); // // 一次读一个字符 // reader = new InputStreamReader(new FileInputStream(file)); // int tempchar; // while ((tempchar = reader.read()) != -1) { // // 对于windows下,\r\n这两个字符在一起时,表示一个换行。 // // 但如果这两个字符分开显示时,会换两次行。 // // 因此,屏蔽掉\r,或者屏蔽\n。否则,将会多出很多空行。 // if (((char) tempchar) != '\r') { // System.out.print((char) tempchar); // } // } // reader.close(); // } catch (Exception e) { // e.printStackTrace(); // } // try { System.out.println("以字符为单位读取文件内容,一次读多个字节:"); // 一次读多个字符 char[] tempchars = new char[30]; int charread = 0; reader = new InputStreamReader(new FileInputStream(fileName)); // 读入多个字符到字符数组中,charread为一次读取字符数 数组读取 while ((charread = reader.read(tempchars)) != -1) { // 同样屏蔽掉\r不显示 if ((charread == tempchars.length) && (tempchars[tempchars.length - 1] != '\r')) { System.out.print(tempchars); } else { for (int i = 0; i < charread; i++) { if (tempchars[i] == '\r') { continue; } else { System.out.print(tempchars[i]); } } } } } catch (Exception e1) { e1.printStackTrace(); } finally { if (reader != null) { try { reader.close(); } catch (IOException e1) { } } } } /** * 以字节为单位读取文件,常用于读二进制文件,如图片、声音、影像等文件。 */ private static void readFilesByBytes() throws IOException { File file = new File("E:/temp.txt"); // 字节 InputStream in = null; in = new FileInputStream(file); try { System.out.println("以字节为单位读取文件内容,一次读一个字节:\n"); // 一次读一个字节 int tempbyte; tempbyte = in.read(); while (tempbyte != -1) { // System.out.print(tempbyte); System.out.write(tempbyte); tempbyte = in.read(); //System.out.println(); //IOTest.showAvailableBytes(in); } // System.out.println(); // System.out.println("-------***------"); } catch (IOException e) { e.printStackTrace(); return; } finally { in.close(); } System.out.println(); /** * System.out.write()输出字符流, System.out.println()是输出字节流。 */ int a = 66; System.out.write(a);// 输出字符流 System.out.println("\n"); System.out.println(a); System.out.println("--------------------以字节为单位读取文件内容,一次读一个字节:\n"); } /** * 以行为单位读取文件,常用于读面向行的格式化文件 */ public static void readFileByLines(String fileName) { File file = new File(fileName); BufferedReader reader = null; try { System.out.println("以行为单位读取文件内容,一次读一整行:"); reader = new BufferedReader(new FileReader(file)); String tempString = null; int line = 1; // 一次读入一行,直到读入null为文件结束 while ((tempString = reader.readLine()) != null) { // 显示行号 System.out.println("line " + line + ": " + tempString); line++; } reader.close(); } catch (IOException e) { e.printStackTrace(); } finally { if (reader != null) { try { reader.close(); } catch (IOException e1) { } } } } /** * 随机读取文件内容 */ public static void readFileByRandomAccess(String fileName) { RandomAccessFile randomFile = null; try { System.out.println("随机读取一段文件内容:"); // 打开一个随机访问文件流,按只读方式 randomFile = new RandomAccessFile(fileName, "r"); // 文件长度,字节数 long fileLength = randomFile.length(); // 读文件的起始位置 int beginIndex = (fileLength > 4) ? 4 : 0; // 将读文件的开始位置移到beginIndex位置。 randomFile.seek(beginIndex); //调整开始读取的位置 byte[] bytes = new byte[10]; int byteread = 0; // 一次读10个字节,如果文件内容不足10个字节,则读剩下的字节。 // 将一次读取的字节数赋给byteread while ((byteread = randomFile.read(bytes)) != -1) { System.out.write(bytes, 0, byteread); } } catch (IOException e) { e.printStackTrace(); } finally { if (randomFile != null) { try { randomFile.close(); } catch (IOException e1) { } } } } /** * 显示输入流中还剩的字节数 */ private static void showAvailableBytes(InputStream in) { try { System.out.println("当前字节输入流中的字节数为:" + in.available()); } catch (IOException e) { e.printStackTrace(); } } /** * A方法追加文件:使用RandomAccessFile */ public static void appendMethodA(String fileName, String content) { try { // 打开一个随机访问文件流,按读写方式 RandomAccessFile randomFile = new RandomAccessFile(fileName, "rw"); // 文件长度,字节数 long fileLength = randomFile.length(); //将写文件指针移到文件尾。 randomFile.seek(fileLength); randomFile.writeBytes(content); randomFile.close(); } catch (IOException e) { e.printStackTrace(); } } /** * B方法追加文件:使用FileWriter */ public static void appendMethodB(String fileName, String content) { try { //打开一个写文件器,构造函数中的第二个参数true表示以追加形式写文件 FileWriter用于写文件 FileWriter writer = new FileWriter(fileName, true); writer.write(content); writer.close(); } catch (IOException e) { e.printStackTrace(); } } }
Math
package ic.lbz.ch09; /** * @author LbZhang * @version 创建时间:2016年6月2日 上午9:58:24 * @description 类说明 */ public class MathDemo { public static void main(String args[]){ /** * abs求绝对值 */ System.out.println(Math.abs(-10.4)); //10.4 System.out.println(Math.abs(10.1)); //10.1 /** * ceil天花板的意思,就是返回大的值,注意一些特殊值 */ System.out.println(Math.ceil(-10.1)); //-10.0 System.out.println(Math.ceil(10.7)); //11.0 System.out.println(Math.ceil(-0.7)); //-0.0 System.out.println(Math.ceil(0.0)); //0.0 System.out.println(Math.ceil(-0.0)); //-0.0 /** * floor地板的意思,就是返回小的值 */ System.out.println(Math.floor(-10.1)); //-11.0 System.out.println(Math.floor(10.7)); //10.0 System.out.println(Math.floor(-0.7)); //-1.0 System.out.println(Math.floor(0.0)); //0.0 System.out.println(Math.floor(-0.0)); //-0.0 /** * max 两个中返回大的值,min和它相反,就不举例了 */ System.out.println(Math.max(-10.1, -10)); //-10.0 System.out.println(Math.max(10.7, 10)); //10.7 System.out.println(Math.max(0.0, -0.0)); //0.0 /** * random 取得一个大于或者等于0.0小于不等于1.0的随机数 */ System.out.println(Math.random()); //0.08417657924317234 System.out.println(Math.random()); //0.43527904004403717 /** * rint 四舍五入,返回double值 * 注意.5的时候会取偶数 */ System.out.println(Math.rint(10.1)); //10.0 System.out.println(Math.rint(10.7)); //11.0 System.out.println(Math.rint(11.5)); //12.0 System.out.println(Math.rint(10.5)); //10.0 System.out.println(Math.rint(10.51)); //11.0 System.out.println(Math.rint(-10.5)); //-10.0 System.out.println(Math.rint(-11.5)); //-12.0 System.out.println(Math.rint(-10.51)); //-11.0 System.out.println(Math.rint(-10.6)); //-11.0 System.out.println(Math.rint(-10.2)); //-10.0 /** * round 四舍五入,float时返回int值,double时返回long值 */ System.out.println(Math.round(10.1)); //10 System.out.println(Math.round(10.7)); //11 System.out.println(Math.round(10.5)); //11 System.out.println(Math.round(10.51)); //11 System.out.println(Math.round(-10.5)); //-10 System.out.println(Math.round(-10.51)); //-11 System.out.println(Math.round(-10.6)); //-11 System.out.println(Math.round(-10.2)); //-10 System.out.println("---------------"); double v=10.5; System.out.println(Math.ceil(v)); System.out.println(Math.round(v)); System.out.println(Math.floor(v)); System.out.println(Math.floor(-5.5)); System.out.println(Math.floor(5.5));//获得比较小的值 数轴 的左侧 } }
Map
package ic.lbz.ch09; import java.util.HashMap; import java.util.Map; /** * @author LbZhang * @version 创建时间:2016年6月2日 下午6:02:45 * @description Java集合类的使用 * * Java集合中有两个主要的接口: * Collection和Map * Collection中存储了一组对象,Map中存储了键值对。 * http://blog.csdn.net/tjcyjd/article/details/11111401 * * Set接口继承Collection接口,而且他不允许集合中存在重复项,每个具体的Set实现类以来添加对象的equals来检查一下独立性 。 */ public class MapTest { public static void main(String[] args) { /** * 两个一样的对象 首先比较hash值然后比较 equals值 */ Person p1 = new Person(1, "aaa"); Person p2 = new Person(1, "aaa"); Map map = new HashMap(); map.put(p2, p1); System.out.println("------------------"); /* * 这里终于搞清楚map.get(p1); * 首先将p1来进行hashcode计算 然后得到当前的key的hash值 获取真实的key然后 p1.equals(key) 返回true * 将返回value * */ Person value = (Person)map.get(p1);// if(value!=null) System.out.println(value.name+"---------"); else System.out.println("can not return value"); } } class Person{ int id; String name; public Person(int id,String name){ this.id = id; this.name=name; } @Override public boolean equals(Object obj) { // TODO Auto-generated method stub System.out.println("equal--------****--------"); if(this==obj) return true; if(obj instanceof Person) return (this.id==((Person)obj).id)&&(this.name.equals(((Person)obj).name)); return false; } /** * Exception in thread "main" java.lang.NullPointerException at ic.lbz.ch09.CollectionTest.main(CollectionTest.java:30) 如果注释掉下面的方法 会报以上的空指针的异常 因为:Map.put(Key,value)会根据key.hashcode()方法生成一个内部的hash值,并且根据这个hash值将对象存储到一个表中 map.get(key)会调用比较hashcode和equals方法,当二者相等的时候,才能正确定位到表。 */ @Override public int hashCode() { // TODO Auto-generated method stub System.out.println("hashcode"+this.name); return id*37; } }
Object
package ic.lbz.ch09; import com.sun.org.apache.xpath.internal.operations.Equals; /** * @author LbZhang * @version 创建时间:2016年6月1日 下午8:18:14 * @description Object方法的学习 * */ public class ObjectMethod { public String name; public int age; public static void main(String[] args) { } @Override public boolean equals(Object obj) { //是否是一个对象 if(this==obj){ return true; } if(obj==null){ return false; } if(this.getClass()!=obj.getClass()){ return false; } ObjectMethod oobj = (ObjectMethod)obj; return (name.equals(oobj.name)) && (age==oobj.age); } @Override public String toString() { return "ObjectMethod[name="+name+",age="+age+"]"; } /** * 主要是将对象在内存的地址转换为int类型返回。这样如果一个类没有覆盖hashcode方法. * hashcode是用于散列数据的快速存取,如利用HashSet/HashMap/Hashtable类来存储数据时 * 都是根据存储对象的hashcode值来进行判断是否相同的。 * * 这样如果我们对一个对象重写了euqals,意思是只要对象的成员变量值都相等那么euqals就等于true, * 但不重写hashcode,那么我们再new一个新的对象,当原对象.equals(新对象)等于true时, * 两者的hashcode却是不一样的,由此将产生了理解的不一致,如在存储散列集合时(如Set类), * 将会存储了两个值一样的对象,导致混淆,因此,就也需要重写hashcode() */ @Override public int hashCode() { //可以用于在后面的hashmap set中的使用 return name.hashCode()*age; } } /** Object() 默认构造方法 clone() 创建并返回此对象的一个副本。 equals(Object obj) 指示某个其他对象是否与此对象“相等”。 finalize() 当垃圾回收器确定不存在对该对象的更多引用时,由对象的垃圾回收器调用此方法。 getClass() 返回一个对象的运行时类。 hashCode() 返回该对象的哈希码值。 notify() 唤醒在此对象监视器上等待的单个线程。 notifyAll() 唤醒在此对象监视器上等待的所有线程。//唤醒等待这个对象的线程 toString() 返回该对象的字符串表示。 wait() 导致当前的线程等待,直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法。 wait(long timeout) 导致当前的线程等待,直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或者超过指定的时间量。 wait(long timeout, int nanos) 导致当前的线程等待,直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或者其他某个线程中断当前线程,或者已超过某个实际时间量。 */
Util
package ic.lbz.ch09; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.Hashtable; import java.util.Iterator; import java.util.LinkedList; import java.util.TreeMap; import java.util.Vector; /** * @author LbZhang * @version 创建时间:2016年6月2日 上午11:16:49 * @description 工具包使用 1.集合类的使用:数组可以存放原始数据变量和对象,但是Java的集合中只能存放对象,不能存放原始的数据变量。 * http://blog.csdn.net/zsw101259/article/details/7570033 */ public class UtilTest { UtilTest() { } public static void main(String[] args) { UtilTest ut = new UtilTest(); ut.testArrayList(); ut.testVector(); ut.testLinkedList(); ut.testHashMap(); ut.testHashTable(); ut.testTreeMap(); } /** * 有序可以按照键值排序 可以放入空值 */ private void testTreeMap() { TreeMap<Integer, Object> tm = new TreeMap<Integer, Object>(); tm.put(1, null); tm.put(2, "2221"); tm.put(3, "333ddd"); tm.put(4, "444721"); tm.put(5, "5ddd"); tm.put(6, "621"); tm.put(7, "7555ddd"); Collection<Object> c = tm.values(); Iterator<Object> it = c.iterator(); System.out.println(c.size()); System.out.println(it.toString()); while (it.hasNext()) { System.out.println(it.next()); } } // 不可以放null 同步的 private void testHashTable() { Hashtable<Integer, Object> ht = new Hashtable<Integer, Object>(); // ht.put(1, null); 这里不可以是空值 ht.put(2, "21"); ht.put(3, "ddd"); ht.put(4, "721"); ht.put(5, "5ddd"); ht.put(6, "621"); ht.put(7, "7ddd"); Collection<Object> c = ht.values(); Iterator<Object> it = c.iterator(); System.out.println(c.size()); System.out.println(it.toString()); while (it.hasNext()) { System.out.println(it.next()); } } // 无序散列表 不是同步的 可以放null private void testHashMap() { HashMap<Integer, Object> hm = new HashMap<Integer, Object>(); hm.put(1, null); hm.put(2, "21"); hm.put(3, "ddd"); hm.put(4, "721"); hm.put(5, "5ddd"); hm.put(6, "621"); hm.put(7, "7ddd"); Collection<Object> c = hm.values(); Iterator<Object> it = c.iterator(); System.out.println(c.size()); System.out.println(it.toString()); while (it.hasNext()) { System.out.println(it.next()); } } /** * LinkedList实现了List接口 允许null元素,此外LinkedList提供额外的get remove * insert方法在LinkedList的首部 或者尾部这些操作使得LinkedList可以被作为栈和队列或者双向队列使用 * * 在多线程下遍历LinkedList,经常会抛出如下异常java.util.ConcurrentModificationException at * java.util.LinkedList$ListItr.checkForComodification(Unknown Source) at * java.util.LinkedList$ListItr.next(Unknown Source) 建议办法是: * 将LinkedList全部换成ConcurrentLinkedQueue试试,LinkedList是线程不安全的。 */ private void testLinkedList() { LinkedList<Integer> v = new LinkedList<Integer>(); v.add(1); v.add(2); v.add(3); Iterator<Integer> it = v.iterator(); System.out.println(v.size()); System.out.println(it.toString()); while (it.hasNext()) { System.out.println(it.next()); } } /** * Vector是同步线程安全的,所以如果需要的是速度,并且不再多线程中使用,最好选用ArrayList * ArrayList是非同步的,当然也不是线程安全的 Vector每次的扩展是100% ArrayList每次扩展是50% * 使用ArrayList可以节省内存空间 */ private void testVector() { Vector<Integer> v = new Vector<Integer>(); v.add(1); v.add(2); v.add(3); Iterator<Integer> it = v.iterator(); System.out.println(v.size()); System.out.println(it.toString()); while (it.hasNext()) { System.out.println(it.next()); } } private void testArrayList() { ArrayList<Integer> al = new ArrayList<Integer>(); al.add(1); al.add(2); al.add(3); Iterator<Integer> it = al.iterator(); System.out.println(al.size()); System.out.println(it.toString()); while (it.hasNext()) { System.out.println(it.next()); } } }
相关文章推荐
- 什么是java同步
- Java EE 中 JSF找不到Bean 的属性
- java可视化编程
- Java千百问_08JDK详解(004)_jdk基础扩展类库都有什么
- Java 开发环境配置
- Java千百问_01基本概念(009)_CLASSPATH是什么
- java之volatile关键字解析
- Java千百问_03基础语法(016)_main方法是什么
- java中的Lock和tryLock方法的详解
- 关于Java中Arrays.sort()方法TLE
- Struts 数字百分比格式化
- 关于java的一些小问题,list中添加对象,java基本数据类型对象
- 十六进制转化为十进制
- spring整合struts2,action里的service注入,空指针异常
- JavaAPI之PropertyDescriptor
- 新手配置springmvc+freemarker过程
- jvisualvm连接远程jvm实例
- java链接数据库--Mysql
- JavaAPI之Introspector
- Spring Boot入门例子