注意:不支持long,double,JDK7之后,开始支持String。
//简单示例
publicclassMyDemo{
publicstaticvoidmain(String... args){
Demo demo = Demo.A;
switch(demo) {
caseA:
break;
caseB:
break;
}
}
enumDemo {
A,
B,
C
}
}
对于几个固定值的判断,建议使用switch语句,因为switch语句会将具体的答案加载进内存,相对高效一点。
饿汉式
privatestaticSingle s =newSingle ( );
privateSingle( ){ }
publicstaticSinglegetInstance()
{
returns ;
}
}
懒汉式
classSingle{
publicstaticSinglegetInstance(){
if( s==null){
synchronized(Single.class){//锁不读可以提高效率
if( s==null){
s = newSingle () ;
}
}
returns ;
}
}
(关于问题1,谢谢 ylt 提醒)
try{
}catch(){
}finally{}
在catch中return(),finally{}会不会执行?
答:会,会在return之后执行。
finally()在什么情况下不会执行
答:只有一种情况不会执行,当执行到System.exit(0)时,finally不会执行。
publicclassTest{
publicstaticvoidmain(String[] args){
System.out.println("haha:"+ haha(true));
}
privatestaticbooleanhaha(booleanisTrue){
try{
inti =1/0;
returnisTrue ? System.out.printf("return try !null ","test") !=null: System.out.printf("return try null ","test") ==null;
} catch(Exception e) {
System.out.println("catch");
returnisTrue ? System.out.printf("return catch !null ","test") !=null: System.out.printf("return catch null ","test") ==null;
} finally{
System.out.println("");
System.out.println("finally");
}
}
}
//打印结果: catch returncatch!null finally haha:true
ArithmeticException, ClassCastException, IllegalArgumentException, IndexOutOfBoundsException, NullPointerException,
先看下面一段代码,运行Test,会打印什么?
package test;
publicclassTest{
publicstaticvoidmain(String... args){
TestA a;
a = newTestA();
a = newTestA();
TestA aa = newTestA();
}
}
classTestA{
{
System.out.println("TestA code create");
}
privateTestB b =newTestB();
privatestaticTestC c =newTestC();
publicTestA(){
System.out.println("TestA create");
}
static{
System.out.println("TestA static create");
}
}
classTestB{
publicTestB(){
System.out.println("TestB create");
}
}
classTestC{
publicTestC(){
System.out.println("TestC create");
}
}
打印结果:
TestC create TestA staticcreate TestA code create TestB create TestA create TestA code create TestB create TestA create TestA code create TestB create TestA create
作用:给对象进行初始化,对象一建立就运行,而且优先于构造函数执行。
和构造函数的区别:
static{
静态代码块中的执行语句;
}
特点:随着类的加载而执行,只执行一次(再new一个对象也不会执行,类只加载一次),
如果定义在有主函数的类中,则优先于主函数执行。用于给类进行初始化。
有些类不用创建对象,无法用构造函数初始化,就通过静态代码块初始化。
执行顺序:静态代码块先执行,如果有对象,构造代码块先执行,然后是构造函数。
如果没有对象,则构造代码块和构造函数都不会执行。
因为接口没有方法体,不会存在两个父类出现同一个方法但是方法体不同的情况,不会引起冲突,如下:
publicclassTestimplementsd{
publicstaticvoidmain(String... args){
}
@Override
publicvoidas(){
}
}
interfacedextendse,f{
}
interfacef{
voidas();
}
interfacee{
voidas();
}
相同点:都是不断向上抽取而来的。不可以被实例化
不同点:
子类的实例化过程:
结论:子类的所有的构造函数,默认都会访问父类中空参数构造函数,因为子类中每一个构造函数内的第一行都有一句隐式的super() ;
当父类中没有空参数的构造函数时,子类必须手动通过super或者this语句形式来指定要访问的构造函数。
当然:子类的构造函数第一行也可以手动指定this语句来访问本类中的构造函数,
子类中至少会有一个构造函数会访问到父类中的构造函数。
见下图:
打印结果:
关于线程这块,后期有时间会写一个完整的深入的文章,这里写的都是比较简单基础的线程的一些知识。
创建线程的两种方式:
继承Thread类。
实现Runnable接口
实现方式相比继承方式的好处:
避免了单继承的局限性(单继承只能继承一个父类)。在定义线程时,建议使用实现方式。
存放代码的位置不一样:
继承Thread:线程代码存放Thread子类的run方法中
实现Runnable,线程代码存在接口的子类的run方法。
将线程的任务从线程的子类中分离出来,进行了单独的封装。按照面向对象的思想将任务的封装成对象。
避免了java单继承的局限性。
同步代码块
synchronized(对象){
需要被同步的代码;
}
同步函数。
将synchronized关键字作为修饰符放在函数上。
public synchronized void add()
同步函数用的是哪一个锁:函数需要被对象调用,那么该函数都有一个所属对象引用,就是this,所以同步函数使用的锁是this(对象)
JDK1.5中提供了多线程升级解决方案,将同步synchronized替换成实现Lock操作,将Object中的wait,notify,notifyAll,替换成了Condition对象的await(),signal(),signalAll(),该对象可以通过Lock锁进行获取。
* 停止线程 原理:run方法结束 1. 使用intrrupt()方法。该方法是结束线程的冻结状态,使线程回到运行状态中来。 当线程处于冻结状态,就不会结束读取到标记,那么线程就不会结束。 当没有指定的方式让冻结的线程恢复到运行状态时,这时需要对冻结进行清除。 强制让线程恢复到运行状态中来,这样就可以操作标记让线程结束。 2. 定义循环结束标记。线程运行代码一般都是循环,只要控制了循环即可。 * 线程常见方法 ```cs 1 setDeamon() 守护线程:setDaemon(ture) ; 也称后台线程,当前台线程执行时后台线程也在执行,但是当前台线程全部执行完关闭时, 后台线程也会跟着自动关闭,jvm退出。 !!该方法必须在启动线程前调用。 2 join()等待该线程终止:一般用于临时加入线程。 当A线程执行到了B线程的.join()方法时,A就会等待,等B线程都执行完,A才会执行 3 yield()方法:释放执行权,让其他线程运行。 暂停当前正在执行的线程对象,并执行其他线程。
一个死锁的 demo
classTestimplementsRunnable{
privatebooleanflag;
Test(booleanflag) {
this.flag = flag;
}
publicvoidrun(){
if(flag) {
while(true)
synchronized(MyLock.locka) {
System.out.println(Thread.currentThread().getName()
+ "..if locka....");
synchronized(MyLock.lockb) {
System.out.println(Thread.currentThread().getName()
+ "..if lockb....");
}
}
} else{
while(true)
synchronized(MyLock.lockb) {
System.out.println(Thread.currentThread().getName()
+ "..else lockb....");
synchronized(MyLock.locka) {
System.out.println(Thread.currentThread().getName()
+ "..else locka....");
}
}
}
}
}
classMyLock{
publicstaticfinalObject locka =newObject();
publicstaticfinalObject lockb =newObject();
}
classDeadLockTest{
publicstaticvoidmain(String[] args){
Test a = newTest(true);
Test b = newTest(false);
Thread t1 = newThread(a);
Thread t2 = newThread(b);
t1.start();
t2.start();
}
}
wait和sleep的区别
1.wait可以指定时间也可以不指定。sleep必须指定时间。 2. 在同步中,对CPU的执行权和锁的处理不同: wait:释放执行权,释放锁 sleep:释放执行权,不释放锁
StringBuffer和StringBuilder的区别
StringBuffer是线程同步(安全)。如果是单线程,效率就比较低
StringBuilder是线程不同步。
List 和 set
List:元素是有序的,元素可以重复,因为该集合体系有索引 Set:元素是无序的,元素不可以重复(存入和取出的顺序不一定一致)。 List特有方法:凡是可以操作角标的方法都是该体系特有的方法
List中常见的三个子类
LinkedList
JDK1.6版本出现的:pollFirst(),pollLast(),peekFirst() ,peekLast(),offerFirst(),offerLast() (如果链表为空,返回null)。 分别替代了remove和get和add(如果链表为空,则抛出异常)。
set常见子类
1. HashSet:底层数据结构是哈希表。 HashSet是如何保证元素的唯一性的: 是通过元素的两个方法,hashCode和equals来完成,如果元素的hashCode值相同, 才会判断equals是否为true,如果元素的hashCode值不同,不会调用equals 。 开发时描述事物,需要往集合里面存时,一般都要复写hashCode和equals。
TreeSet底层的数据结构:二叉树
保证数据元素唯一性的依据compareTo方法return 0,为0则表示是相同元素 ;
排序的两种方式: TreeSet排序的第一种方式: 让元素自身具备比较性。元素需要实现Comparable接口,覆盖compareTo方法。这种方式也称为元素的自然顺序,或者叫做默认顺序。 TreeSet的第二种排序方式: 当元素自身不具备比较性时,或具备的比较性不是所需要的,这是就需要让集合自身具备比较性。 定义一个比较器,将比较器对象作为参数传递给TreeSet集合的构造函数。 定义一个类,实现Comparator接口,覆盖compare方法 当两种排序都存在时,以比较器为主。
泛型技术是给编译器使用的技术,用于编译时期。确保了类型的安全。
运行时,会将泛型去掉,生成的class文件中是不带泛型的,这个称为泛型的擦除。
为什么擦除呢?因为为了兼容运行的类加载器。
泛型的补偿:在类加载器原有基础上,编写一个补偿程序。在运行时,通过反射,
获取元素的类型进行转换动作。不用使用者在强制转换了。
常见子类
Hashtable:底层是哈希表数据结构,不可以存入null键null值,该集合是线程同步的。jdk1.0,效率低 。 HashMap:底层是哈希表数据结构,并允许使用null键null值,该集合不是同步的,jdk1.2,效率高。 TreeMap :底层是二叉树数据结构,线程不同步,可以给map集合中的键进行排序 。 Map和Set很像 :其实,Set底层使用了Map集合 。
map集合的两种取出方式:
1.Set<K> KeySet: 将Map中所有的Key存到了Set集合中,因为Set集合具备迭代器。 所有可以迭代方式取出所有的键,再根据get方法,获取每一个键对应的值 Map集合的取出原理:将Map集合转成Set集合,再通过迭代器取出 2.Set<Map.Entry<K,V>> entrySet:将Map集合中的映射关系存入到了Set集合中,而这个关系的数据类型就是:Map.Entry。 Map.Entry :其实Entry也是一个接口,它是Map接口中的一个内部接口。 先有Map,才有映射关系,所有Entry类定义在Map内部
Math类:
doubled = Math.ceil(12.56);// 13.0 。ceil返回大于指定整数的最小整数 doubled1 =Math.floor(12.34);//12.0 。floor返回小于指定数据的最大整数 longl = Math.round(12.64);//四舍五入 doubled2 = Math.pow(2,3);//幂运算 :2^3 = 8
字节流:InputStream(读) OutputStream(写)
RandomAccessFile(断点下载会用到的类):
随机访问文件,自身具备读写的方法。
通过skipBytes(int x),seek(int x)来达到随机访问。
seek(int x):调整对象中指针,指针跳转,可以实现对数据指定位置的读取和写入。
IO流体系:
字符流: Reader |--BufferedReader: |--LineNumberReader |--CharArrayReader |--StringReader |--InputStreamReaer |--FileReader Writer |--BufferedWriter |--CharArrayWriter |--StringWriter |--OutputStreamWriter |--FileWriter |--PrintWriter 字节流: InputStream |--FileInputStream: |--FilterInputStream |--BufferedInputStream |--DataInputStream |--ByteArrayInputStream |--ObjectInputStream |--SequenceInputStream |--PipedInputStream OutputStream |--FileOutputStream |--FilterOutputStream |--BufferedOutputStream |--DataOutputStream |--ByteArrayOutputStream |--ObjectOutputStream |--PipedOutputStream |--PrintStream
示例:读出C盘下txt文件
publicstaticvoidlistDemo_2(){
File dir = newFile("c://");
String[] names = dir.list(newSuffixFilter(".txt"));
for(String name : names){
System.out.println(name);
}
}
publicclassSuffixFilterimplementsFilenameFilter{
privateString suffix ;
publicSuffixFilter(String suffix){
super();
this.suffix = suffix;
}
@Override
publicbooleanaccept(File dir, String name){
returnname.endsWith(suffix);
}
}
示例:深度递归,读出制定目录下的所有文件和文件夹,包括子目录。
publicclassFileTest{
publicstaticvoidmain(String[] args){
File dir = newFile("D://me//mime//RuntimePermissions");
listAll(dir,0);
}
/**
*
* @paramdir
* @paramspaceLevel 这个是为了打印结果好看,与空格有关的参数
*/
publicstaticvoidlistAll(File dir,intspaceLevel){
System.out.println(getSpace(spaceLevel)+dir.getName());
//获取指定目录下当前的所有文件夹或者文件对象
spaceLevel++;
File[] files = dir.listFiles();
for(intx=0; x<files.length; x++){
if(files[x].isDirectory()){
listAll(files[x],spaceLevel);
}
else
System.out.println(getSpace(spaceLevel)+files[x].getName());
}
}
privatestaticStringgetSpace(intspaceLevel){
StringBuilder builder = newStringBuilder();
builder.append("|--");
for(intx=0; x<spaceLevel; x++){
builder.insert(0,"| ");
}
returnbuilder.toString();
}
}