那些你所不知道的Java小知识(持续更新)

本文主要是收录一些人们可能经常会忽略,但又挺重要的Java方面的小知识。有推荐的也可以在下方留言,大家一起进步呀!

目录:
1.a=a+b和a+=b的区别
2.String str1 = new String("a"); String str2 = "a"+"b"; 这两行代码分别创建了几个对象,是什么
3.启动线程的方式以及如何更好地结束一个线程?
4.Java 中 == 和 equals 和 hashCode的区别
5.Java浮点数的默认类型是什么
6.多态成员访问特点
7.用来实现线程间通知和唤醒的方式
8.初始化过程
9.值传递和引用传递
10.线程共享的内容和私有的内容
11.Thread和Runnable的区别
12.迭代器遍历元素的时候,通过集合是不能修改元素的
13.EditText中的值为手机号时不能转为int

2019-7-7

1.a=a+b和a+=b的区别

(1)从效率上看
a+=b要略高于a=a+b
(2)从运算符上看
a+=b的执行过程是先计算出a的值,然后用一个temp对象存储,之后和b进行相加,然后将值赋给a引用。
a=a+b的执行过程是先计算a+b,然后再赋值给a引用,赋值给a引用的时候如果引用a有计算过程,则会再次计算。
(3)从类型自动转换上看
当a和b的数据类型不一样时,a+=b会自动进行类型转换;而a=a+b不会,需要手动进行类型转换
比如:

byte a = 1;
int b = 4;
a = a + b;//此时编译会报错,因为a为byte,b为int,
//a+b的时候默认会向大类型即int转换,则a+b的类型为int,而a为byte,所以报错

a += b;//此时编译不会报错,因为+=会自动进行类型转换,并且向低转换
2.String str1 = new String("a"); String str2 = "a"+"b"; 这两行代码分别创建了几个对象,是什么

(1)首先第一行代码中创建了两个对象(因为字符串池中没有a字符串),一个是new String创建出来的str1对象,一个是在字符串池中创建的a对象。
(2)然后因为a字符串已经在常量池中存在了,所以在第二行代码中就不会再创建a对象了。接着创建的就是b对象,最后是str2对象,值为ab。
总结:要先看字符串池中有没有该字符串,有的话会直接拿过来,没有再重新创建。

3.启动线程的方式以及如何更好地结束一个线程?

(1)启动线程的方式

  • 继承Thread类
  • 实现Runnable接口
  • 实现Callable接口通过FutureTask包装器来创建Thread线程
  • 匿名内部类
图片.png

(2)如何更好地结束一个线程

线程中调用interrupt()方法仅仅是在当前线程中打了个停止的标记,并不是真的停止线程。
如何判断线程的状态是否是停止,主要包含以下两种方法:
1、this.interrupted():测试当前线程是否已经是中断状态,执行后具有将状态标志置清除为false的功能。
2、this.isInterrupted():测试线程thread对象是否已经是中断状态,但不具备清除状态标志。
注:使用stop()方法停止线程是非常暴力的,该方法已经作废,不考虑。

注意:官方文档中说明If this thread is blocked in an invocation of the [wait()], [wait(long)], or [wait(long, int)] methods of the [Object] class, or of the [join()], [join(long)], [join(long, int)], [sleep(long)], or [sleep(long, int)], methods of this class, then its interrupt status will be cleared and it will receive an [InterruptedException].
也就是说,在run方法里面调用Object类的wait或线程的join/sleep方法之后,这个标记会被清空并抛出InterruptedException异常。解决方法:可在调用的方法的catch中再this.interrupt一次。(不是下文例子中的catch)

① 抛异常法

public static void main(String[] args) throws InterruptedException {
        MyThread t1 = new MyThread();
        t1.start();
        Thread.sleep(100);
        t1.interrupt();
    }

    public static class MyThread extends Thread {
        @Override
        public void run() {
            try {
                for (int i = 0; i < 5000000; i++) {
                    if (this.isInterrupted()) {
                        System.out.println("Thread Stop!");
                        throw new InterruptedException();
                    }
                    System.out.println("i: " + i);
                }
                System.out.println("我在for下面");
            } catch (InterruptedException e) {
                System.out.println("进入到catch了!");
            }
        }
    }

运行结果:
...
i: 11759
i: 11760
i: 11761
i: 11762
Thread Stop!
进入到catch了!

② 使用return

public static void main(String[] args) throws InterruptedException {
        MyThread t1 = new MyThread();
        t1.start();
        Thread.sleep(100);
        t1.interrupt();
    }

    public static class MyThread extends Thread {
        @Override
        public void run() {
            for (int i = 0; i < 5000000; i++) {
                if (this.isInterrupted()) {
                    System.out.println("Thread Stop!");
                    return;
                }
                System.out.println("i: " + i);
            }
            System.out.println("我在for下面");
        }
    }

运行结果:
...
i: 12301
i: 12302
i: 12303
i: 12304
i: 12305
Thread Stop!

③ 使用退出标志
和上面两种方法差不多,只不过是用一个布尔变量代替this.isInterrupted(),然后要想停止线程,赋值该布尔变量为false即可。

2019-8-2

4.Java 中 == 和 equals 和 hashCode的区别

(1)==
对于八种基本数据类型,比较的是他们的值
对于引用数据类型(类,接口和数组),比较的是他们在内存中的地址,所以,除非是同一个new出来的对象,他们比较之后的结果为true,否则为false。eg:

Integer a = new Integer(127);
Integer b = 127;
Integer c = 127;
//a==b为false,b==c为true
Integer d = 128;
Integer e = 128;
//d==e为false
//这里为什么b==c为true而d==e为false呢?
//Integer b = 127在编译时会被翻译成Integer.valueOf(127),该方法对于[-128,127]之间
//的数会进行缓存,如果已经有的话会直接从缓存中拿出,不会再new
//因为128不在该区间,那么d和e就只是new出来的两个不同的对象了,所以就为false

Java中堆和栈的区别
最主要的区别就是:new出来的对象和数组是存放在堆中的,基本数据类型的变量和对象的引用变量是存放在栈中的。

Java的内存机制:
栈:当在一段代码块定义一个变量时,Java就在栈中为这个变量分配内存空间,当该变量超过它的作用域后,Java会自动释放掉为该变量所分配的内存空间。
堆:在堆中分配的内存,由GC来管理。在堆中产生了一个数组或对象之后,还可以在栈中定义一个特殊的变量,让栈中这个变量的值等于该数组或者对象在堆内存中的首地址,栈中的这个变量就成了数组或者对象的引用变量,以后可以在程序中使用栈中的引用变量来访问数组或者对象。

(2)equals
默认情况下的equals方法是没有被覆盖的,调用的都是Object类的equals方法,这种情况下的equals方法和==是等效的。

public boolean equals(Object obj) {
   return (this == obj);
   }
如果equals方法被覆盖,则按照新的方法来判断,覆盖后一般
都是通过对象的内容是否相等来判断对象是否相等。比如String类的equals方法:

public boolean equals(Object anObject) {
   if (this == anObject) {
       return true;
   }
   if (anObject instanceof String) {
       String anotherString = (String)anObject;
       int n = count;
       if (n == anotherString.count) {
       char v1[] = value;
       char v2[] = anotherString.value;
       int i = offset;
       int j = anotherString.offset;
       while (n-- != 0) {
           if (v1[i++] != v2[j++])
           return false;
       }
       return true;
       }
   }
   return false;
}

String类的equals方法总结为:
首先看是不是同一个对象,是的话返回true
然后看对比对象是不是String类型,
接着看长度是否一致
最后比较逐个字符是否相同

实现高质量的equals方法的技巧如下:
首先比较两个是否==,
然后检查对比对象是否是该类型,
接着比较他们的域是否相同
最后检查对称性,传递性,一致性

(3)hashCode
hashCode()方法也是Object类的一个方法,返回的是一个int型的整数。在集合类操作中使用,主要是为了提高查询速度。
两者的hashCode相同,他们不一定equals。
两者的hashCode不相同,他们一定不equals。
他们equals,hashCode一定相同。
他们不equals,hashCode有可能相同。

2019-8-9

5.Java浮点数的默认类型是什么

答案:double。

6.多态成员访问特点

成员变量:编译看左边,运行看左边
静态变量:编译看左边,运行看左边
成员方法:编译看左边,运行看右边
静态方法:编译看左边,运行看左边

7.用来实现线程间通知和唤醒的方式

① Object.wait/notify/notifyAll
② Condition.await/signal/signalAll

2019-8-10

8.初始化过程

① 首先,初始化父类中的静态成员变量和静态代码块,按照在程序中出现的顺序初始化;
② 然后,初始化子类中的静态成员变量和静态代码块,按照在程序中出现的顺序初始化;
③ 其次,初始化父类的普通成员变量和代码块,在执行父类的构造方法;
④ 最后,初始化子类的普通成员变量和代码块,在执行子类的构造方法;
比如:

class C {
    C() {
        System.out.print("C");
    }
}
 
class A {
    C c = new C();
 
    A() {
        this("A");
        System.out.print("A");
    }
 
    A(String s) {
        System.out.print(s);
    }
}
 
class Test extends A {
    Test() {
        super("B");
        System.out.print("B");
    }
 
    public static void main(String[] args) {
        new Test();
    }
}

Output:
CBB

(1)初始化父类的普通成员变量和代码块,执行 C c = new C(); 输出C 
(2)super("B"); 表示调用父类的构造方法,不调用父类的无参构造函数,输出B 
(3) System.out.print("B"); 
 所以输出CBB 

2019-8-23

9.值传递和引用传递

“在Java里面参数传递都是按值传递”这句话的意思是:按值传递是传递的值的拷贝,按引用传递其实传递的是引用的地址值,所以统称按值传递。

简单的说,

基本类型是按值传递,方法的实参是一个原值的副本。
类对象是按对象的引用地址(内存地址)传递地址的值,那么在方法内对这个对象进行修改是会直接反应在原对象上的(或者说这两个引用指向同一内存地址)。
但是String类除外,其规则和基本类型是一样的,因为String是final关键字修饰的,不可变的
eg:

public static void main(String[] args){
  String x = new String("LongSh1z");
  change(x);
  System.out.println(x);
}

public static void change(String x){
  x = "changed";
}

输出结果应该是LongSh1z,而不是changed。

解释如下:

当执行到change方法时,Main就入栈,change开启一片栈空间,x是形参,在change的栈内有一份拷贝引用x。(这时Main栈上的x和change栈上的是指向同一片堆空间,即“LongSh1z”)。接着执行x = "changed",此时change栈上的x会指向新的一片空间(方法区上的常量池),而Main栈上的x没有改变。

还不懂的同学可以去看看这一篇,讲的巨详细
https://blog.csdn.net/bntx2jsqfehy7/article/details/83508006

2019-9-5

10.线程共享的内容和私有的内容

(1)线程共享的内容包括:
进程代码段
进程 数据段
进程打开的文件描述符
信号的处理器
进程的当前目录
进程用户 ID 与进程组 ID
(2)线程独有的内容包括:
线程 ID
寄存器组的值
线程的堆栈
错误返回码
线程的信号屏蔽码

2019-9-17

11.Thread和Runnable的区别

(1)Runnable方式可以避免Thread方式由于Java单继承的特性带来的缺陷
(2)Runnable的代码可以被多个线程(Thread实例)共享,适合于多个线程处理同一资源(这里的同一资源指的是同一个Runnable对象)的情况

2019-10-26

12.迭代器遍历元素的时候,通过集合是不能修改元素的
List<Integer> list = new ArrayList<>();
        list.add(1);
        list.add(6);

        Iterator<Integer> iterator = list.iterator();
        while(iterator.hasNext()){
            list.add(6);
            System.out.println(iterator.next());
        }

//会报Exception in thread "main" java.util.ConcurrentModificationException异常

//正确做法:
//①使用ListIterator(List集合特有的迭代器。该迭代器继承了Iterator迭代器)
ListIterator iterator= list.listItertor();
while(lit.hasNext()){
    String s = (String)lit.next();
    if(s.equals("java")){
        iterator.add("love");
//注意:此处是利用迭代器进行添加元素,刚添加的元素处于刚才迭代的元素的后面。
//!!!是iterator添加,不是list添加。!!!
    }
}
 
//②使用普通循环方法,即使用get()方法
for(int i = 0;i<list.size();i++){
    String s = (String)list.get(i);
    if(s.equals("java")){
        list.add("love");//注意:此处是将新的元素添加到了集合的最后
    }
}

//③要想继续使用Iterator而不是ListIterator ,可以将ArrayList改为CopyOnWriteArrayList

2019-10-27

13.EditText中的值为手机号时不能转为int

很多时候我们都需要拿到editText里面的值,并且转为int,但是每次Integer.parseInt()时拿到的值都为0。
参照了网上的方法(比如转化之前判断呀,try-catch呀,在监听器里面写呀等等)都没用。
网上的方法可以点击这个看看:http://blog.sina.com.cn/s/blog_a4dda2480101asy3.html
但是最重要的如果editText里面的是String类型的手机号码转为int的话,可以将int改为long。
因为在Java中int的范围是从-21474836482147483647(10位),即2的31次方,而手机号码为11位

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 200,961评论 5 473
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,444评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 148,009评论 0 333
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,082评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,101评论 5 363
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,271评论 1 278
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,738评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,395评论 0 255
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,539评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,434评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,481评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,160评论 3 317
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,749评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,816评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,038评论 1 256
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,548评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,140评论 2 341

推荐阅读更多精彩内容

  • 从网上复制的,看别人的比较全面,自己搬过来,方便以后查找。原链接:https://www.cnblogs.com/...
    lxtyp阅读 1,341评论 0 9
  • 前言 RTFSC (Read the fucking source code )才是生活中最重要的。我们天天就是要...
    二毛_coder阅读 442评论 1 1
  • 在C语言中,五种基本数据类型存储空间长度的排列顺序是: A)char B)char=int<=float C)ch...
    夏天再来阅读 3,311评论 0 2
  • 一:在JAVA中,有六个不同的地方可以存储数据: 1. 寄存器(register)。 这是最快的存储区,因为它位...
    辰321阅读 405评论 0 0
  • 总概 - 命名规范 - 数据类型 - eclipse常用快捷键 1、java开发中的命名规则 除去一些硬性要求,比...
    panda_Hi阅读 323评论 0 0