首頁 >Java >java教程 >Java知識總結詳情介紹(圖)

Java知識總結詳情介紹(圖)

黄舟
黄舟原創
2017-03-20 11:07:361548瀏覽

目前在搞 Node.js,曾經的 JAVA 知識忘了好多,為此整理了一下,感嘆下工業語言還是有相當的優勢的。

目錄

  • #註解

  • 安全性

  • 類別載入

  • 關鍵字

  • 初始化

  • 多執行緒

  • #執行緒池

  • 記憶體模型

Java所有的流類別位於java.io套件中,都分別繼承字以下四種抽象流類型。

輸入流InputStreamReader
Type 字節流 #字元流
##########輸出流######OutputStream#######Writer################################################################ #######

继承自InputStream/OutputStream的流都是用于向程序中输入/输出数据,且数据的单位都是字节(byte=8bit)。

继承自Reader/Writer的流都是用于向程序中输入/输出数据,且数据的单位都是字符(2byte=16bit)。

异常

Java的异常(包括Exception和Error)分为:

可查的异常(checked exceptions)

除了RuntimeException及其子类以外,其他的Exception类及其子类都属于可查异常。这种异常的特点是Java编译器会检查它,也就是说,当程序中可能出现这类异常,要么用try-catch语句捕获它,要么用throws子句声明抛出它,否则编译不会通过。

不可查的异常(unchecked exceptions)

包括运行时异常(RuntimeException与其子类)和错误(Error)。

运行时异常和非运行时异常:

RuntimeException

NullPointerException(空指针异常)、IndexOutOfBoundsException(下标越界异常)等这些异常是不检查异常,程序中可以选择捕获处理,也可以不处理。这些异常一般是由程序逻辑错误引起的,程序应该从逻辑角度尽可能避免这类异常的发生。运行时异常的特点是Java编译器不会检查它,也就是说,当程序中可能出现这类异常,即使没有用try-catch语句捕获它,也没有用throws子句声明抛出它,也会编译通过。

RuntimeException以外的Exception

从程序语法角度讲是必须进行处理的异常,如果不处理,程序就不能编译通过。如IOException、SQLException等以及用户自定义的Exception异常,一般情况下不自定义检查异常。

注解

Java SE5内置了三种标准注解:

 @Override,表示当前的方法定义将覆盖超类中的方法。

 @Deprecated,使用了注解为它的元素编译器将发出警告,因为注解@Deprecated是不赞成使用的代码,被弃用的代码。

 @SuppressWarnings,关闭不当编译器警告信息。

Java还提供了4中注解,专门负责新注解的创建:

@Target:

表示该注解可以用于什么地方,可能的ElementType参数有:
CONSTRUCTOR:构造器的声明
FIELD:域声明(包括enum实例)
LOCAL_VARIABLE:局部变量声明
METHOD:方法声明
PACKAGE:包声明
PARAMETER:参数声明
TYPE:类、接口(包括注解类型)或enum声明

@Retention

表示需要在什么级别保存该注解信息。可选的RetentionPolicy参数包括:
SOURCE:注解将被编译器丢弃
CLASS:注解在class文件中可用,但会被VM丢弃
RUNTIME:VM将在运行期间保留注解,因此可以通过反射机制读取注解的信息

@Document

将注解包含在Javadoc中

@Inherited

允许子类继承父类中的注解

Example

定义注解:

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface UseCase {
    public String id();
    public String description() default "no description";
}

使用注解:

public class PasswordUtils {
     @UseCase(id = 47, description = "Passwords must contain at least one numeric")
     public boolean validatePassword(String password) {
         return (password.matches("\\w*\\d\\w*"));
     }

     @UseCase(id = 48)
     public String encryptPassword(String password) {
         return new StringBuilder(password).reverse().toString();
     }
 }

解析注解

public static void main(String[] args) {
     List<Integer> useCases = new ArrayList<Integer>();
     Collections.addAll(useCases, 47, 48, 49, 50);
     trackUseCases(useCases, PasswordUtils.class);
 }

 public static void trackUseCases(List<Integer> useCases, Class<?> cl) {
     for (Method m : cl.getDeclaredMethods()) {
         UseCase uc = m.getAnnotation(UseCase.class);
         if (uc != null) {
             System.out.println("Found Use Case:" + uc.id() + " "
                         + uc.description());
             useCases.remove(new Integer(uc.id()));
         }
     }
     for (int i : useCases) {
         System.out.println("Warning: Missing use case-" + i);
     }
 }
 // Found Use Case:47 Passwords must contain at least one numeric
 // Found Use Case:48 no description
 // Warning: Missing use case-49
 // Warning: Missing use case-50

安全性

  1. 严格遵循面向对象的规范。这样封装了数据细节,只提供接口给用户。增加了数据级的安全性。

  2. 无指针运算。java中的操作,除了基本类型都是引用的操作。引用是不能进行增减运算,不能被直接赋予内存地址的,从而增加了内存级的安全性。

  3. 数组边界检查。这样就不会出现C/C++中的缓存溢出等安全漏洞。

  4. 强制类型转换。非同类型的对象之间不能进行转换,否则会抛出ClassCastException

  5. 语言对线程安全的支持。java从语言级支持线程。从而从语法和语言本身做了很多对线程的控制和支持。

  6. 垃圾回收。

  7. Exception。

类加载

原理

ClassLoader使用的是双亲委托模型来搜索类的,每个ClassLoader实例都有一个父类加载器的引用(不是继承的关系,是一个包含的关系),虚拟机内置的类加载器(Bootstrap ClassLoader)本身没有父类加载器,但可以用作其它ClassLoader实例的的父类加载器。

当一个ClassLoader实例需要加载某个类时,它会试图亲自搜索某个类之前,先把这个任务委托给它的父类加载器,这个过程是由上至下依次检查的,首先由最顶层的类加载器Bootstrap ClassLoader试图加载,如果没加载到,则把任务转交给Extension ClassLoader试图加载,如果也没加载到,则转交给App ClassLoader 进行加载,如果它也没有加载得到的话,则返回给委托的发起者,由它到指定的文件系统或网络等URL中加载该类。

如果它们都没有加载到这个类时,则抛出ClassNotFoundException异常。否则将这个找到的类生成一个类的定义,并将它加载到内存当中,最后返回这个类在内存中的Class实例对象。

JVM在判定两个class是否相同时,不仅要判断两个类名是否相同,而且要判断是否由同一个类加载器实例加载的。只有两者同时满足的情况下,JVM才认为这两个class是相同的。

加载器

BootStrap ClassLoader

启动类加载器,是Java类加载层次中最顶层的类加载器,负责加载JDK中的核心类库,如:rt.jar、resources.jar、charsets.jar等。

   URL[] urls = sun.misc.Launcher.getBootstrapClassPath().getURLs();
   for (int i = 0; i < urls.length; i++) {
       System.out.println(urls[i].toExternalForm());  
   }
   // 也可以通过sun.boot.class.path获取
   System.out.println(System.getProperty("sun.boot.class.path"))

Extension ClassLoader

扩展类加载器,负责加载Java的扩展类库,默认加载JAVA_HOME/jre/lib/ext/目下的所有jar。

App ClassLoader

系统类加载器,负责加载应用程序classpath目录下的所有jar和class文件

注意:

除了Java默认提供的三个ClassLoader之外,用户还可以根据需要定义自已的ClassLoader,而这些自定义的ClassLoader都必须继承自java.lang.ClassLoader类,
也包括Java提供的另外二个ClassLoader(Extension ClassLoader和App ClassLoader)在内。
Bootstrap ClassLoader不继承自ClassLoader,因为它不是一个普通的Java类,
底层由C++编写,已嵌入到了JVM内核当中,当JVM启动后,Bootstrap ClassLoader也随着启动,
负责加载完核心类库后,并构造Extension ClassLoader和App ClassLoader类加载器。

关键字

strictfp(strict float point)

strictfp 关键字可应用于类、接口或方法。使用strictfp关键字声明一个方法时,该方法中所有的float和double表达式都严格遵守FP-strict的限制,符合IEEE-754规范。当对一个类或接口使用strictfp关键字时,该类中的所有代码,包括嵌套类型中的初始设定值和代码,都将严格地进行计算。严格约束意味着所有表达式的结果都必须是 IEEE 754算法对操作数预期的结果,以单精度和双精度格式表示。

如果你想让你的浮点运算更加精确,而且不会因为不同的硬件平台所执行的结果不一致的话,可以用关键字strictfp。

transiant

变量修饰符,如果用transient声明一个实例变量,当对象存储时,它的值不需要维持。

Volatile

作为指令关键字,确保本条指令不会因编译器的优化而省略,修饰变量,保证变量每次都是从内存中重新读取。

final

  1. 修饰基础数据成员(as const)

  2. 修饰类或对象的引用

  3. 修饰方法的final(cannot overwrite)

  4. 修饰类或者参数

初始化

父静态->子静态
父变量->父初始化区->父构造
子变量->子初始化区->子构造

多线程

java多线程实现方式主要有三种:继承Thread类、实现Runnable接口、使用ExecutorService、Callable、Future实现有返回结果的多线程。其中前两种方式线程执行完后都没有返回值,只有最后一种是带返回值的。

线程池

concurrent下的线程池:

名称 功能
ExecutorService 真正的线程池接口
ScheduledExecutorService 能和Timer/TimerTask类似,解决那些需要任务重复执行的问题
ThreadPoolExecutor ExecutorService的默认实现
ScheduledThreadPoolExecutor 继承ThreadPoolExecutor的ScheduledExecutorService接口实现,周期性任务调度的类实现

Executors

newSingleThreadExecutor

建立一個單執行緒的執行緒池。這個執行緒池只有一個執行緒在工作,也就是相當於單執行緒串列執行所有任務。如果這個唯一的執行緒因為異常結束,那麼會有一個新的執行緒來取代它。此執行緒池保證所有任務的執行順序都按照任務的提交順序執行。

newFixedThreadPool

#建立固定大小的執行緒池。每次提交一個任務就建立一個線程,直到線程達到線程池的最大大小。執行緒池的大小一旦達到最大值就會保持不變,如果某個執行緒因為執行異常而結束,那麼執行緒池會補充一個新執行緒。

newCachedThreadPool

#建立一個可快取的執行緒池。如果線程池的大小超過了處理任務所需的線程,那麼就會回收部分空閒(60秒不執行任務)的線程,當任務數增加時,此線程池又可以智慧的新增線程來處理任務。此線程池不會對線程池大小做限制,線程池大小完全依賴作業系統(或者說JVM)能夠創建的最大線程大小。

newScheduledThreadPool

#建立一個大小無限的執行緒池。此線程池支援定時以及週期性執行任務的需求。

記憶體模型

Java記憶體模型規定,對於多個執行緒共享的變量,儲存在主記憶體當中,每個執行緒都有自己獨立的工作內存,線程只能訪問自己的工作內存,不可以訪問其它線程的工作內存。工作記憶體中保存了主記憶體共享變數的副本,執行緒要操作這些共享變量,只能透過操作工作記憶體中的副本來實現,操作完畢之後再同步回到主記憶體當中。

如何保證多個執行緒操作主記憶體的資料完整性是一個難題,Java記憶體模型也規定了工作記憶體與主記憶體之間互動的協議,首先是定義了8種原子操作:

  • lock:將主記憶體中的變數鎖定,為一個執行緒所獨佔

  • unclock:將lock加的鎖定解除,此時其它的執行緒可以有機會存取此變數

  • read:將主記憶體中的變數值讀到工作記憶體當中

  • load:將read讀取的值儲存到工作記憶體中的變數副本。

  • use:將值傳遞給執行緒的程式碼執行引擎

  • #assign:將執行引擎處理傳回的值重新賦值給變數副本

  • store:將變數副本的值儲存到主記憶體。

  • write:將store儲存的值寫入到主記憶體的共享變數當中。

記憶體組成

#堆(Heap)

運行時資料區域,所有類別實例和陣列的記憶體均從此處分配。 Java虛擬機器啟動時建立。物件的堆記憶體由稱為垃圾回收器 的自動記憶體管理系統回收。

  • News Generation(Young Generation即圖中的Eden + From Space + To Space)

    • Eden 存放新生的物件

    • Survivor Space 兩個存放每次垃圾回收後存活的物件

  • Old Generation(Tenured Generation 即圖中的Old Space ) 主要存放應用程式中生命週期長的存活物件

#非堆疊記憶體

##JVM具有一個由所有執行緒共享的方法區。方法區屬於非堆記憶體。它儲存每個類別結構,如運行時常數池、欄位和方法數據,以及方法和

建構方法的程式碼。它是在Java虛擬機器啟動時創建的。除了方法區外,Java虛擬機實作可能需要用於內部處理或最佳化的內存,這種內存也是非堆內存。例如,JIT編譯器需要記憶體來儲存從Java虛擬機器程式碼轉換而來的本機程式碼,從而獲得高效能。

  • Permanent Generation  (圖中的Permanent Space)存放JVM自己的反射對象,例如類別對象與方法對象

  • native heap

以上是Java知識總結詳情介紹(圖)的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn