回过头来想了想,将所有知识点杂七杂八的整理在一起,实际上并没有太多收获,没有一个完整的结构;因此在思考再三之下,我觉得可以将Java分为四个大部分进行整理。

个人觉得理解Java最好的方式可能是从英语的角度去理解,包括理解词的词性也是非常重要的,再后面我会一一举例子;有时候你不用拼命去记,按照高中的英语语法,词根词性也能很自然地记住。甚至有时候即使忘记了,也能根据词性进行推论。

  1. Java的语言特性
  2. Java库
  3. JVM
  4. Java生态

我个人的理解前面两个是基础,后面才是优化拔高。一上来就研究JVM实际上我觉得没有太多的必要,如果JVM提到某个Java关键字或者知识点你都不知道平时用在哪里的,那怎么知道去优化;也就是鸡蛋都没有你总不能上来就炒鸡蛋饭吧。

而Java语言特性我觉得又可以分为两大部分,关键字和结构;如果说关键字是血肉,那么结构则是Java的灵魂,比如设计模式。因此在这一篇里则是介绍一些关键字的具体细节,而对于之前那样的整理则是准备摒弃掉了。不过之前的那篇也并不是没有用,它是从Java的大尺度上的生命周期进行了讲解,在之后的学习中,你至少可以理清问题发生在哪个阶段。在这一篇里,则是更深入的接触源码,那才是经得起千锤百炼的最优秀的工程;而我的作用大概只能提醒大家这个知识点值得学习。

Exception 和 Error

Exception 和 Error 都是继承了 Throwable 类,一般的代码里实际用到的都是Exception,表示这个错误可预测可被捕捉到。

而Error此类错误一般表示代码运行时 JVM 出现问题。通常有 Virtual MachineError(虚拟机运行错误)、NoClassDefFoundError(类定义错误)等。比如 OutOfMemoryError:内存不足错误;StackOverflowError:栈溢出错误。此类错误发生时,JVM 将终止线程。

这些错误是不受检异常,非代码性错误,是不可预测的。因此,当此类错误发生时,应用程序不应该去处理此类错误。按照Java惯例,我们是不应该实现任何新的Error子类的!

对于Exception与之相关联的关键字有try,catch,finally,throw,throws。

// 文件名 : ExcepTest.java
import java.io.*;
public class ExcepTest{public static void main(String args[]){try{int a[] = new int[2];System.out.println("Access element three :" + a[3]);}catch(ArrayIndexOutOfBoundsException e){System.out.println("Exception thrown  :" + e);}System.out.println("Out of the block");}
}

实际上高中英语里就有try to do sth,也就是这个单词后面接动作,因此可以知道代码的执行都是try块的;而catch sth则是抓住某物,因此后面是接名词的,例如括号里的异常。那么加上finally之后呢,我们知道这是个副词,因此后面也可以接带有动作的句子例如(it's you who said he would love me forever. But finally you abandoned me.)反应在Java语言里就是finally也和try一样是一个代码块,并且从名字也能知道是最后的要执行的代码块。这也是为什么不用其它代表最后的单词,例如Last,它也要照顾到final关键字。

public class ExcepTest{public static void main(String args[]){int a[] = new int[2];try{System.out.println("Access element three :" + a[3]);}catch(ArrayIndexOutOfBoundsException e){//继承自RuntimeException ,即使你不catch系统也会自动这个错System.out.println("Exception thrown  :" + e);}finally{a[0] = 6;System.out.println("First element value: " +a[0]);System.out.println("The finally statement is executed");}}
}

我们从英语的角度理解,可能有的觉得太麻烦了,因为还要额外地记忆那么多英语语法,词性什么的。但实际用到的都是基本的语法,总不能发明一门语言,结果这门语言里全是高级语言,那谁懂得了。并且我们从英语角度去理解Java语言也是很有必要的,第一它是一门语言,第二它是以英语为母语的外国人发明的。

对于throws/throw 关键字,首先在英语里throws是throw的第三人称,因此throws前面肯定是有东西的,也就是它接在方法名后面,throws的后面依旧是接名词Exception。平时我们在读写文件的时候,IDE就会自动地提醒必须throws一个Exception,它代表了可能但不一样抛出异常。

而对于throw原始形式,因此前面没有东西后面直接接异常就好了,执行throw则必定会抛出异常。

import java.io.*;
public class className
{public void deposit(double amount) throws RemoteException{// Method implementationthrow new RemoteException();}//Remainder of class definition
}

注意下面事项:

  • catch 不能独立于 try 存在。
  • 在 try/catch 后面添加 finally 块并非强制性要求的。
  • try 代码后不能既没 catch 块也没 finally 块。
  • try, catch, finally 块之间不能添加任何代码。
class GFG
{ public static void main (String[] args)  { // array of size 4. int[] arr = new int[4]; try{ int i = arr[4]; // this statement will never execute // as exception is raised by above statement System.out.println("Inside try block"); } finally{ System.out.println("finally block executed"); } // rest program will not execute System.out.println("Outside try-finally clause"); }
} 

而对于为什么Java中异常处理时为什么可以只要try-finally,而可以不要catch。

try只适合处理运行时异常,try+catch适合处理运行时异常+普通异常。也就是说,如果你只用try去处理普通异常却不加以catch处理,编译是通不过的,因为编译器硬性规定,普通异常如果选择捕获,则必须用catch显示声明以便进一步处理。而运行时异常在编译时没有如此规定,所以catch可以省略,你加上catch编译器也觉得无可厚非。

int和Integer

Java 虽然号称是面向对象的语言,但是原始数据类型仍然是重要的组成元素,所以在Java里不仅有原始数据类型的int也有它的包装类Integer。

int 是我们常说的整形数字,是 Java 的 8 个原始数据类型(Primitive Types,boolean、byte 、short、char、int、float、double、long)之一。Java 语言虽然号称一切都是对象,但原始数据类型是例外。这里面int对应的是Integer,char对应的是Character,其他的都只是将首字母大写了。

Integer 是 int 对应的包装类,它有一个 int 类型的字段存储数据,并且提供了基本操作,比如数学运算、int 和字符串之间转换等。在 Java 5 中,引入了自动装箱和自动拆箱功能(boxing/unboxing),Java 可以根据上下文,自动进行转换,极大地简化了相关编程。Cache to support the object identity semantics of autoboxing for values between* -128 and 127 (inclusive) as required by JLS.

这里涉及到了Java的自动拆箱自动装箱, Java中基础数据类型与它们的包装类进行运算时,编译器会自动帮我们进行转换,转换过程对程序员是透明的,这就是装箱和拆箱,装箱和拆箱可以让我们的代码更简洁易懂。我们可以通过几个小例子理解下,这其实和我很久之前讲的python类似

int型的

public class Main {public static void main(String[] args) {Integer i1 = 100;Integer i2 = 100;Integer i3 = 200;Integer i4 = 200;System.out.println(i1==i2);System.out.println(i3==i4);}
}
#输出
true
false

double型的:

public class Main {public static void main(String[] args) {Double i1 = 100.0;Double i2 = 100.0;Double i3 = 200.0;Double i4 = 200.0;System.out.println(i1==i2);System.out.println(i3==i4);}
}
#输出
false
false

boolean型的:

public class Main {public static void main(String[] args) {Boolean i1 = false;Boolean i2 = false;Boolean i3 = true;Boolean i4 = true;System.out.println(i1==i2);System.out.println(i3==i4);}
}
#输出
true
true

其实输出true还是false,只要看看源码就有发现,比如对于int类型的

public static Integer valueOf(int i) {if(i >= -128 && i <= IntegerCache.high)return IntegerCache.cache[i + 128];elsereturn new Integer(i);}

IntegerCache的实现如下:

private static class IntegerCache {static final int low = -128;static final int high;static final Integer cache[];static {// high value may be configured by propertyint h = 127;String integerCacheHighPropValue =sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");if (integerCacheHighPropValue != null) {try {int i = parseInt(integerCacheHighPropValue);i = Math.max(i, 127);// Maximum array size is Integer.MAX_VALUEh = Math.min(i, Integer.MAX_VALUE - (-low) -1);} catch( NumberFormatException nfe) {// If the property cannot be parsed into an int, ignore it.}}high = h;cache = new Integer[(high - low) + 1];int j = low;for(int k = 0; k < cache.length; k++)cache[k] = new Integer(j++);// range [-128, 127] must be interned (JLS7 5.1.7)assert IntegerCache.high >= 127;}private IntegerCache() {}}

从这2段代码可以看出,在通过valueOf方法创建Integer对象的时候,如果数值在[-128,127]之间,便返回指向IntegerCache.cache中已经存在的对象的引用;否则创建一个新的Integer对象。上面的代码中i1和i2的数值为100,因此会直接从cache中取已经存在的对象,所以i1和i2指向的是同一个对象,而i3和i4则是分别指向不同的对象。

这种缓存机制并不是只有 Integer 才有,同样存在于其他的一些包装类,比如:Boolean,缓存了 true/false 对应实例,确切说,只会返回两个常量实例 Boolean TRUE/FALSE。Short,同样是缓存了 -128 到 127 之间的数值。Byte,数值有限,所以全部都被缓存。Character,缓存范围’u0000’ 到 ‘u007F’。

ArrayList<Integer> list = new ArrayList<>();

对于集合类的初始化,我们知道一直用的是带有大写字母的也就是包装类型的。而这么做的原因是Java集合中实际存放的只是对象的引用,每个集合元素都是一个引用变量,实际内容都放在堆内存或者方法区里面,但是基本数据类型是在栈内存上分配空间的,栈上的数据随时就会被收回的。

Java的装箱与拆箱

Integer integer = 1;
int unboxing = integer ++;#反编译输出
1: invokestatic  #2                  // Method
java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
8: invokevirtual #3                  // Method
java/lang/Integer.intValue:()I

可以看到用的是valueOf(),拆箱用的是intValue()。

缓存上限值实际是可以根据需要调整的,JVM 提供了参数设置:

-XX:AutoBoxCacheMax=N

原则上,建议避免无意中的装箱、拆箱行为,尤其是在性能敏感的场合,创建 10 万个 Java 对象和 10 万个整数的开销可不是一个数量级的,不管是内存使用还是处理速度,光是对象头的空间占用就已经是数量级的差距了。

原始类型线程安全问题

  • 原始数据类型的变量,显然要使用并发相关手段,才能保证线程安全,这些我会在专栏后面的并发主题详细介绍。如果有线程安全的计算需要,建议考虑使用类似 AtomicInteger、AtomicLong 这样的线程安全类。
  • 特别的是,部分比较宽的数据类型,比如 float、double,甚至不能保证更新操作的原子性,可能出现程序读取到只更新了一半数据位的数值!

参考博客:

https://www.cnblogs.com/dolphin0520/p/3780005.html

https://blog.csdn.net/qq_42253147/article/details/100302644

https://www.runoob.com/java/java-exceptions.html

cookie里面用到的关键字_Java的理解角度-关键字篇相关推荐

  1. 什么是java的关键字_java中常见的关键字

    什么是关键字呢? 概述:关键字就是在java语言中赋予特殊含义的单词 特点:1.组成的关键字的单词全是小写 2.常见的代码编辑器中,对关键字都有特殊的颜色标记 比如在idea中对关键字都有特殊的颜色标 ...

  2. java transient 关键字_java中的transient关键字详解

    前言 说实话学了一段时间java的朋友对于transient这个关键字依旧很陌生基本没怎么用过,但是transient关键字在java中却起到了不可或缺的地位!如果要说讲到,我觉得最可能出现的地方是I ...

  3. java中的me关键字_java中的volatile关键字

    一.详细解释 在java线程并发处理中,有一个关键字volatile的使用目前存在很大的混淆,以为使用这个关键字,在进行多线程并发处理的时候就可以万事大吉. Java语言是支持多线程的,为了解决线程并 ...

  4. final关键字_Java中的final关键字

    我们都知道,Java是面向对象的语言,而面向对象有一种思想就是继承.但是有时候,出于某种原因,我们不希望我们的类.方法或者变量被继承或重写,这个时候,我们就需要final关键字来帮助我们达到这种效果. ...

  5. java修饰类的关键字_JAVA中的修饰关键字

    今天我们来说说JAVA中的修饰关键字. 常用的有: 1.final 关键字 修饰成员变量:a. 必须初始化值. b. 被fianl修饰的成员变量赋值,有两种方式:1.直接赋值 2.全部在构造方法中赋初 ...

  6. java中有效关键字_java中有效的关键字

    true.false.null都不是关键字 goto.const.是保留的关键字 abstract continue for new switch default if package synchro ...

  7. java static关键字_Java基础:static关键字作用总结

    前言 之前讲到final关键字的作用是每次面试的时候我必问求职者的两个问题之一,另外一个问题就是文本会写到的static.final和static一样,都是一个小问题可以看到一个人的基础是否扎实以及平 ...

  8. java中default关键字_Java 中的 default 关键字及代码示例

    本文通过代码示例介绍如何在 Java 中使用 default 关键字. 基本上,有 3 个地方可以使用 Java 中的 default 关键字: 在 switch case 语句中指定默认值 在 Ja ...

  9. java异常类关键字_Java中的异常处理关键字是什么?

    java异常处理中使用了四个关键字. throw:有时我们明确要创建异常对象然后抛出它来停止程序的正常处理.throw关键字用于向运行时抛出异常来处理它. throws:当我们在方法中抛出任何已检查的 ...

  10. java排他锁关键字_Java并发之synchronized关键字深度解析(一)

    前言 近期研读路神之绝世武学,徜徉于浩瀚无垠知识之海洋,偶有攫取吉光片羽,惶恐未领略其精髓即隐入岁月深处,遂急忙记录一二,顺备来日吹cow之谈资.本小系列为并发之亲儿子-独臂狂侠synchronize ...

最新文章

  1. 目前银行利息高还是余额宝利息高?如何选择?
  2. java 数字 下划线_为什么要在Java SE 7的数字中使用下划线-在数字文字中使用下划线...
  3. 【C/C++】递归算法
  4. Redhat 6.8部署oracle 12c
  5. OSI参考模型和TCP/IP参考模型
  6. ++[[]][+[]]+[+[]] == 10 //true
  7. linux服务器数据备份到本地硬盘_如何备份硬盘数据,最简单的方法是什么?
  8. sersync实现多台服务器实时同步文件
  9. java 可以做前端么_java怎么做前端?Java web前端必备技术
  10. 2022下半年软件设计师资源分享
  11. android 二进制编辑器,二进制编辑器
  12. 【Python从入门到精通】(二十八)五万六千字对Python基础知识做一个了结吧【值得收藏】
  13. Android Thermal
  14. 华硕ac68u最佳设置_华硕AC68U路由器APP远程控制设置教程
  15. srand函数怎么用linux,rand与srand函数的使用
  16. 称重软件测试工程师,无人值守称重管理系统研发团队
  17. 你们公司的产品[zhuan]
  18. 你所不知道的OneNote骚操作 | 告别枯燥 OneNote让数学教学更有趣
  19. Dungeon Master POJ - 2251 BFS
  20. mysql8.0安装设置密码_mysql8.0.11安装配置方法图文教程 MySQL8.0新密码认证方式

热门文章

  1. DPDK数据流过滤规则例程解析—— 网卡流处理功能窥探
  2. Shell脚本-tr 将大写字母变为小写
  3. linux中/etc/fstab文件删除或修改了,导致系统无法启动
  4. read()/write()的生命旅程——前言与目录
  5. 注册(六)之有效期过小
  6. 注册(四)之删除绑定
  7. Oracle bad magic 1,linux下Oracle的安装
  8. NYOJ2-括号配对问题
  9. php过滤除了文字数据英文,正则:过滤除英文和汉字的其它特殊符号
  10. node.js require模板报错_简历不知道如何写起,推荐几个简历模板