Java基础知识
宏志有缘再见
用脑思考永远都是学习的最好方法。
展开
-
判断输入的日期是否合法并输出该日期对应星期几
《算法4》的课后练习题1.2.11,页码为72页。实现一个SmartDate类,在日期非法时抛出异常,并添加一个dayOfTheWeek()方法,输出这天是星期几。public class SmartDate { private int year; private int month; private int day; public SmartDate(int...原创 2019-08-07 18:43:53 · 599 阅读 · 0 评论 -
输入/输出流
在Java API中,可以从其中读入一个字节序列的对象称做输入流,而可以向其中写入一个字节序列的对象称做输出流。这些字节序列的来源地和目的地可以是文件,而且通常都是文件,但是也可以是网络连接,甚至是内存块。抽象类InputStream和OutputStream构成了输入/输出(I/O)类层次结构的基础。因为面向字节的流不便于处理以Unicode形式存储的信息,所以从抽象类Reader和Writ...原创 2019-04-22 22:32:13 · 151 阅读 · 0 评论 -
原子性
java.uitl.concurrent.atomic包中有很多类使用了很高效的机器级指令(而不是使用锁)来保证其它操作的原子性。例如,AtomicInterger类提供了方法incrementAndGet和decrementAndGet,它们分别以原子方式将一个整数自增或自减。AtomicInteger atomicInteger = new AtomicInteger(1);//以原子...原创 2019-04-18 09:46:34 · 476 阅读 · 0 评论 -
为克隆使用序列化
序列化为克隆对象提供了一种简便的途径,只要对应的类是可序列化的即可。其做法很简单:直接将对象序列化到输出流中,然后将其读回。这样产生的新对象是对现有对象的一个深拷贝。在此过程中,我们不必将对象写出文件中,因为可以用ByteArrayOutputStream将数据保存在字节数组中。具体做法就是拓展SerialCloneablepublic class SerialCloneable impl...原创 2019-04-26 21:35:23 · 129 阅读 · 0 评论 -
序列化中的版本管理
如果使用序列化来保存对象,就需要考虑在程序演化时会出现的问题。例如,新版本可以读入旧文件吗?旧版本可以读入新版本产生的文件吗?乍一看,这好像是不能的。无论类的定义产生了什么样的变化,它的SHA指纹也跟着变化,而我们都知道对象输入流将拒绝读入具有不同指纹的对象。但是,类可以表明它对早期版本保持兼容,要想这样做,就必须首先获得这个类的早期版本指纹。这个类的所有较新的版本都必须把serialVers...原创 2019-04-26 21:17:24 · 500 阅读 · 0 评论 -
对象输入/输出流与序列化
Java语言支持一种称为对象序列化的非常通用的机制,它可以将任何对象写出到输入流中,并在之后将其读回。一.保存和加载序列化对象为了保存对象数据,首先需要打开一个ObjectOutputStream对象。可以直接使用ObjectOutputStream的writeObject方法。对应的,将对象读回,首先需要获得一个ObjectInputStream对象,然后用readObject方法以这...原创 2019-04-26 18:15:47 · 684 阅读 · 0 评论 -
final变量
除了使用锁或volatile修饰符,还有一种情况可以安全地访问一个共享域,即这个域声明为final时。final Map<String, Double> accounts = new HashMap<>();其它线程会在构造函数完成构造之后才看到这个accounts变量。如果不使用final,就不能保证其它线程看到的是accounts更新后的值,它们可能都只是...原创 2019-04-17 17:33:27 · 96 阅读 · 0 评论 -
ZIP文档
ZIP文档(通常)以压缩格式存储了一个或多个文件,每个ZIP文档都有一个头,包含诸如每个文件名字和所使用的压缩方法等信息。在Java中,可以使用ZipInputStream来读入ZIP文档。浏览文档中每个单独的项,getNextEntry方法就可以返回一个描述这项的ZipEntry类型的对象。向ZipInputStream的getInputStream方法传递该项可以获取用于读取该项的输入流。然...原创 2019-04-26 15:09:20 · 986 阅读 · 0 评论 -
带资源的try语句
如下代码 try{ //codes in = new FileInputStream("..."); //codes } catch (IOException e){ e.getStackTrace(); }finally { try { ...原创 2019-04-14 16:44:47 · 127 阅读 · 0 评论 -
finally子句
当代码抛出一个异常时,就会终止方法中剩余代码的处理,并退出这个方法的执行。如果方法获得了一些本地资源,并且只有这个方法自己知道,又如果这些资源在退出方法之前必须回收,那么就会产生资源回收问题。可以将资源回收的代码放入finally子句中。因为不管是否有异常捕获,finally子句中的代码都会执行。分析以下代码InputStream in = new FileInputStream(".....原创 2019-04-14 16:05:00 · 343 阅读 · 0 评论 -
捕获异常
一.异常捕获如果某个异常发生时没有在任何地方进行捕获,那程序就会终止执行,并在控制台上打印出异常信息,其中包括异常的类型和堆栈的内容。想要捕获一个异常,必须设置try/catch语句块,如下方public void read(String filename){ try { FileInputStream in = new FileInputStre...原创 2019-04-14 11:58:18 · 890 阅读 · 0 评论 -
自定义异常
在程序中,可能会遇到任何标准异常类都没有能够充分地描述清楚的问题。在这种情况下,创建自己的异常类就是一件顺理成章的事情了。我们需要做的只是定义一个派生于Exception的类,或者派生于Exception子类的类。例如,定义一个派生于IOException 的类。习惯上,定义的类应该包含两个构造器,一个是默认的构造器;另一个是带有详细描述信息的构造器。public class FileF...原创 2019-04-14 10:50:29 · 82 阅读 · 0 评论 -
Volatile域
volatile关键字为实例域的同步访问提供了一种免锁机制。如果声明一个域为volatile,那么编译器和虚拟机就知道该域是可能被另一个线程并发更新的。例如,假定一个对象有一个布尔标记done,它的值被线程设置却被另一个线程查询,可以使用锁private boolean done;public synchronized boolean isDone() { return done;...原创 2019-04-17 09:24:34 · 142 阅读 · 0 评论 -
异常
一.异常的作用假设在一个Java程序运行期间出现了一个错误。这个错误可能是文件包含了错误信息,或者网络连接出现问题造成的,也可能是因为使用无效的数组下标,或者试图使用一个没有被赋值的对象引用造成的。异常处理的任务就是将控制权从错误产生的地方转移给能够处理这种情况的错误处理器。在Java中,如果某个方法不能够采用正常的途径完整它的任务,就可以通过另外一个路径退出方法。在这种情况下,方法并不返...原创 2019-04-13 18:08:36 · 150 阅读 · 0 评论 -
同步阻塞
每个Java对象都有一个锁。线程可以通过调用同步方法获得锁。还有另一种机制可以获得锁,通过进入一个同步阻塞。当线程进入如下形式的阻塞public class Bank { private Object lock = new Object(); public void transfer(int from,int to,int amount){ synchroni...原创 2019-04-16 18:05:33 · 409 阅读 · 0 评论 -
ThreadLocal线程局部变量
有时可能要避免共享变量,使用ThreadLocal辅助类为各个线程提供各自的实例。例如,SimpleDateFormat类不是线程安全的。可以这样处理:public class ThreadLocalTest { public static final ThreadLocal<SimpleDateFormat> dateFormat = Thre...原创 2019-04-18 11:13:22 · 157 阅读 · 0 评论 -
锁测试和超时
线程在调用lock方法获得另一个线程所持有的锁的时候,很可能发生阻塞。应该更加谨慎地申请锁。tryLock方法试图申请一个锁,在成功获得锁后返回true,否则,立即返回false,而且线程可以立即离开去做其他事情。if(myLock.tryLock()){ //获得锁 try{...} finally { myLock.unlock(); }}else ...原创 2019-04-18 11:51:32 · 288 阅读 · 0 评论 -
读/写锁
如果很多线程从一个数据结构读取数据而很少线程修改其中数据的话,可以使用java.util.concurrent.locks.ReentrantReadWriteLock。在这种情况下,允许对读者线程共享访问是合适的。当然,写者线程依然必须是互斥访问的。public class ReentrantReadWriteLockTest { //构造一个ReentrantReadWriteLock...原创 2019-04-18 12:06:31 · 97 阅读 · 0 评论 -
String两次赋值可能得到两个不同对象
在Java中,除了基本数据类型之外,其他数据类型均为对象。常见的String,数组均为对象。对象在赋值时,会传递地址,两个变量指向同一个地址。String string1 = "hello";String string2 = string1;StdOut.println(string2.hashCode() == string1.hashCode());结果为true这时为str...原创 2019-08-06 20:59:56 · 1345 阅读 · 0 评论 -
随机访问文件
RandomAccessFile类可以在文件中的任何位置查找或写数据。磁盘文件都是随即访问的,但是与网络套接字通信的输入/输出流却不是。打开一个随机文件,只用与读入或者同时用于读写,可以通过使用字符串r(用于读入访问)或rw(用于读入/写出访问)作为构造器的第二个参数来指定这个选项。RandomAccessFile in = new RandomAccessFile("C:\\Users\\...原创 2019-04-25 16:51:01 · 807 阅读 · 0 评论 -
Fork-Join框架
假设想要统计一下数组中有多少个元素满足某个特定的属性。可以将这个数组一分为二,分别对这两部分进行统计,再将结果相加。public class ForkJoinTest { public static void main(String[] args) { final int SIZE = 10000000; double[] numbers = new ...原创 2019-04-20 16:02:58 · 93 阅读 · 0 评论 -
读写二进制数据
一.DataInput 和DataOutput接口DataOutput接口定义了下面用于以二进制格式写数组,字符,boolean值和字符串的方法: public void writeBoolean(boolean v) throws IOException {} public void writeByte(int v) throws IOException {} public void...原创 2019-04-24 22:28:33 · 220 阅读 · 0 评论 -
控制任务组
将一个执行器服务作为线程池使用,以提高执行任务的效率。有时,使用执行器有更有实际意义的原因,控制一组相关任务。例如,可以在执行器中使用shutdownNow方法取消所有的任务。invokeAny方法提交所有对象到一个Callable对象的集合中,并返回某个已经完成了的任务的结果。无法知道返回的究竟是哪个任务的结果。invokeAll方法提交所有对象到一个Callable对象的集合中,并返回一...原创 2019-04-20 12:25:00 · 178 阅读 · 0 评论 -
预定执行
ScheduledExecutorService接口具有为预定执行或重复执行任务而设计的方法。它是一种允许使用线程池机制的java.util.Timer的泛化。Executors类的newCachedThreadPool和newSingleThreadScheduledExecutor方法将返回实现了ScheduledExecutorService接口的对象。可以预定Runnable或Call...原创 2019-04-20 11:48:17 · 123 阅读 · 0 评论 -
线程池
构建一个新的线程是有一定代价的,因为涉及与操作系统的交互。如果程序中创建了大量的生命期很短的线程,将Runnable对象交给线程池。一个线程池中包含许多准备运行的空闲线程。将Runnable对象交给线程池,就会有一个线程调用run方法,当run方法退出时,线程不会死亡,而是在池中准备为下一个请求提供服务。另一个使用线程池的理由是减少并发线程的数目。创建大量线程会大大降低性能,甚至使虚拟机崩溃。...原创 2019-04-20 11:35:22 · 83 阅读 · 0 评论 -
Callable与Future
Runnable封装一个异步运行的任务,可以把它想象成为一个没有参数和返回值的异步方法。Callable与Runnable类似,但是有返回值。Callable接口是一个参数化的类型,只有一个方法call。public interface Callable<V> { //计算并返回结果 V call() throws Exception;}类型参数是返回值类型。例...原创 2019-04-20 10:01:11 · 135 阅读 · 0 评论 -
文本输入与输出
一.文本输入在保存数据时,可以选择二进制格式或文本格式。例如,整数1234存储成二进制数时,它被写为00 00 04 D2构成的序列(十六进制表示法),而存储成文本格式时,它被存成了字符串"1234"。尽管二进制格式的I/O高效,但是不宜人来阅读。在存储文本字符串时,需要考虑字符编码方式。在Java内部使用的UTF-16编码方式中,字符串"1234"编码 00 21 00 32 00 33 ...原创 2019-04-24 18:28:21 · 712 阅读 · 0 评论 -
阻塞队列
对于实际编程来说,应该尽可能远离底层结构。使用由并发处理的专业人士实现的较高层次的结构要方便得多,要安全得多。对于许多线程问题,可以通过使用一个或多个队列以优雅且安全的方式将其形式化。生产者线程向队列插入元素,消费者线程调用它们。使用队列,可以安全地从一个线程向另一个线程传递数据。例如,考虑银行转账程序,转账线程将转账指令对象插入一个队列中,而不是直接访问银行对象。另一个线程从队列中取出指令执...原创 2019-04-18 17:49:46 · 963 阅读 · 0 评论 -
访问目录中的项
静态的Files.list方法会返回一个可以读取目录中各个项的Stream<Path>对象。目录是被惰性读取的,这使得处理具有大量项的目录可以变得高效//因为读取目录涉及需要关闭的系统资源,所以应该使用try块try(Stream<Path> entries = Files.list(pathToDirectory)){ } catch (IOException ...原创 2019-04-27 20:50:30 · 128 阅读 · 0 评论 -
获取文件信息
下面的静态方法都将返回一个boolean值,表示检查路径的某个属性的结果。existsisHiddenisReadable,isWritadble,isExecutableisRegularFile,isDirectory,isSymbolicLinksize方法返回文件的字节数:Files.size(path);Files.getOwner(path);方法将文件的拥有者作为...原创 2019-04-27 13:07:09 · 226 阅读 · 0 评论 -
操作文件
Path和Files类封装了在用户机器上处理文件系统所需的所有功能。例如,Files类可以用来移除或重命名文件,或者查询文件最后被修改的时间。换句话说,输入/输出流类关心的是文件的内容,而Path和Files类关心的是在磁盘上如何储存文件。一.PathPath表示的是一个目录名序列,其后还可以跟着一个文件名。路径中的第一个部件可以是根部件,例如 / 或 C:\ ,而允许访问的根部件取决于...原创 2019-04-27 10:54:30 · 242 阅读 · 0 评论 -
弃用stop和suspend方法
初始的Java版本定了一个stop方法用来终止一个线程,以及一个suspend方法用来阻塞一个线程直到另一个线程调用resume。stop和suspend方法有一些共同点:都视图控制一个给定的线程行为。stop,suspend和resume方法已经弃用。stop方法天生就不安全,经验证明suspend方法会经常导致死锁。stop方法终止所有未结束的方法,包括run方法。在模拟银行转账中,假定...原创 2019-04-18 14:30:34 · 246 阅读 · 0 评论 -
synchronized关键字
Lock和Condition接口为程序设计人员提供了高度的锁定控制。然而,大多数情况下,并不需要那样的控制,并且可以使用一种嵌入到Java语言内部的机制。从1.0版开始,Java中的每一个对象都有一个内部锁。如果一个方法用synchronized关键字声明,那么对象的锁将保护整个方法。也就是说,要调用该方法,线程必须获得内部的对象锁。内部对象锁只有一个相关条件。wait方法添加一个线程到等待集...原创 2019-04-16 17:38:59 · 86 阅读 · 0 评论 -
同步器
java.util.concurrent包包含了几个能帮助人们管理相互合作的线程集的类。这些机制具有为线程之间的共用集结点模式提供的预置功能。如果有一个相互合作的线程集满足这些行为模式之一,那么应该直接重用合适的库类而不要试图提供手工锁与条件结合。一.信号量概念上讲,一个信号量管理许多的许可证明。为了通过信号量,线程通过调用acquire请求许可。其实没有实际的许可对象,信号量仅维护一...原创 2019-04-20 18:10:46 · 209 阅读 · 0 评论 -
可完成Future
处理非阻塞调用的传统方法是使用事件处理器,程序员为任务完成之后出现的动作注册一个处理器。当然,如果下一个动作也是异步的,在它之后的下一个动作会在一个不同的事件处理器中。尽管程序员会认为,先做步骤1,然后是步骤2,再完成步骤3,但实际上程序逻辑会分散到不同的处理器中。如果必须增加错误处理,情况会更糟糕。假设步骤2是用户登录。可能需要重复这个步骤,因为用户输入凭据时可能会出错。要尝试在一组事件处理器...原创 2019-04-20 17:16:21 · 315 阅读 · 0 评论 -
HashSet散列集
一.HashSet的意义链表和数组可以按照人们的意愿排列元素的次序。但是,如果想要查看某个指定的元素,却又忘记了它的位置,就需要访问所有的元素,直到找到为止。如果集合中包含的元素很多,将会消耗很多时间。如果不在意元素的顺序,可以有几种能够快速查找元素的数据结构。其缺点是无法控制元素出现的次序。它们将按照有利于其操作目的的原则组织数据。有一种众所周知的数据结构,可以快速地查找所需要的对象,这就...原创 2019-03-18 21:59:51 · 1468 阅读 · 1 评论 -
LinkedList链表
一.链表与数组以及ArrayList类的区别从数组的中间位置删除一个元素要付出很大的代价,其原因是数组中处于被删除元素之后的所有元素都要向数组的前端移动。在数组中间位置上插入一个元素也是如此。链表解决了这个问题。尽管数组在连续的存储位置上存放对象的引用,但链表却将每个对象存放在独立的结点中。每个结点还存放着序列中下一个结点的引用。在Java程序设计语言中,所有链表实际上都是双向链接的—即每...原创 2019-03-18 18:13:29 · 228 阅读 · 0 评论 -
具体的集合
一.集合类型与描述集合类型描述ArrayList一种可以动态增长和缩减的索引序列LinkedList一种可以在任何位置进行高效地插入和删除操作的有序序列ArrayDeque一种用循环数组实现的双端队列HashSet一种没有重复元素的无序集合TreeSet一种有序集EnumSet一种包含枚举类型值的集LinkedHashSet一...原创 2019-03-17 21:04:10 · 147 阅读 · 0 评论 -
集合框架中的接口
一.集合框架的接口Java框架为不同类型的集合定义了大量接口二.集合类型集合有两种基本接口:Collection和Map。两者之间的区别,如://在Collection中插入元素boolean add(E element);//在Map中插入元素V put(K key,V value);//从Collection中读取元素c.iterator();//从Map中读取...原创 2019-03-17 20:39:27 · 215 阅读 · 0 评论 -
Comparable<T>接口
一.为什么要实现Comparable接口Arrays类中的sort方法承诺可以对对象数组进行排序,但是必须以实现Comparable<T>接口为前提。实现Comparable<T>接口,主要是重写compareTo方法。但是不能直接为类提供一个compareTo方法,因为Java程序设计语言是一种强类型,编译器将会检查这个方法是否存在。二.实例public cl...原创 2019-03-16 17:00:32 · 666 阅读 · 0 评论