Java 語言對我來講即熟悉又陌生的語言,原來是特別喜歡Java,就以爲它是世界最好的語言。 設計的規範很是好,代碼看起來很是完整,還有巨大的組件/jar庫。 總之來講是很是強大。 隨着幾年沒有接觸過它,慢慢就忘記它了。 就比如一輛車,以前一直常常開以爲很順手,如今從新開起發現當年的感受比較難找到了。【重拾JAVA】php
根據java的語法生成java文件/類文件,而後經過javac 工具,直接把java文件加載到JVM,而後生成字節碼。 應用請求JRE環境,JRE把class執行結果返回給應用。html
Java SE: CLI 請求JRE環境->調用/生成class文件->調用本地庫->輸出java
Java語言的解析器,能夠把類文件編譯生成class文件的過程。總的過程:1. 歸類: 把執行的對象和變量/對象申請內存塊,放到heap裏面,把方法放到方法區域; 2.解析和執行過程:對於類文件,先編譯,若是有存在空對象/空指針等報錯會拋出人釋放內存,執行完後垃圾回收內存;3. 調用本地系統的方法,如文件,I/O等方法,生成class 文件。python
類加載的主要思路:對於引用的類,會先在classpath配置裏面找找到就會加載,否則繼續向上找,知道找到rt.jar,若是還不存在,這報錯"ClassNotFoundException"nginx
總的來講:加載class文件->驗證->分配內存空間->符號解析,變量、常量池->初始化可使用了c++
Java 基礎知識就是怎麼根據Java API生成java類文件。 Java API包含了組件/工具以下圖結構描述:git
對象裏面包含了屬性和方法,經過Main函數啓動CLI 進程來執行對類文件的解析。web
public class Bicycle {
int speed = 1;
int gear = 1;
public void addSpeed(int value){
this.speed += value;
}
public int getSpeed(){
return this.speed;
}
public int getGear(){
return this.gear;
}
}
public class Main {
public static void main(String[] args) {
System.out.println("Hello World!");
Bicycle b = new Bicycle();
b.addSpeed(3);
b.addSpeed(4);
System.out.println("Speed value :"+b.getSpeed());
System.out.println("Gear value :"+b.getGear());
}
}
複製代碼
public class RoadBicycle extends Bicycle {
private int road =1;
public void setRoad(int val){
this.road += val;
//增長加速值
this.road += this.getGear();
}
public int getRoad(){
return this.road;
}
}
複製代碼
public class Disk implements Circle{
private int weight = 100;
public void setWeight(){
this.weight += 10;
}
public int getLength() {
return this.weight/3;
}
public int getRadius() {
return this.weight/2;
}
}
複製代碼
public int[] getArray(){
int [] anArray = new int [10];;
for(int i=0; i<10; i++)
{
anArray[i] = i+10;
}
return anArray;
}
複製代碼
public void invokeCalculator(){
Calculator myApp = new Calculator();
IntegerMath addition = (a, b) -> a + b;
IntegerMath subtraction = (a, b) -> a - b;
System.out.println("40 + 2 = " +
myApp.operateBinary(40, 2, addition));
System.out.println("20 - 10 = " +
myApp.operateBinary(20, 10, subtraction));
}
複製代碼
註解是一種元數據形式,提供有關不屬於程序自己的程序的數據。註解對他們註釋的代碼的操做沒有直接的影響。
註解的做用:
註解能夠聲明字段,類,方法,屬性等
@Target: 說明了Annotation所修飾的對象範圍:Annotation可被用於 packages、types(類、接口、枚舉、Annotation類型)、類型成員(方法、構造方法、成員變量、枚舉值)、方法參數和本地變量(如循環變量、catch參數)。
@Retention定義了該Annotation被保留的時間長短 : 1.SOURCE:在源文件中有效;2.CLASS:在class文件中有效;3.RUNTIME:在運行時有效
@Documented : 用於描述其它類型的annotation應該被做爲被標註的程序成員的公共API
@Inherited 元註解是一個標記註解,@Inherited闡述了某個被標註的類型是被繼承的。
定義註解格式:
  public @interface 註解名 {定義體}
複製代碼
泛型的做用:在定義類,接口和方法時,泛型使類型(類和接口)成爲參數。
經常使用的類型參數
E - Element (used extensively by the Java Collections Framework)
K - Key
N - Number
T - Type
V - Value
S,U,V etc. - 2nd, 3rd, 4th types
複製代碼
public class OrderedPair<K, V> implements Pair<K, V> {
private K key;
private V value;
public OrderedPair(K key, V value) {
this.key = key;
this.value = value;
}
public K getKey() { return key; }
public V getValue() { return value; }
}
public interface Pair<K, V> {
public K getKey();
public V getValue();
}
//泛型的處理
Pair<String, Integer> p1 = new OrderedPair<String, Integer>("Even", 8);
System.out.println("Generic key :" + p1.getKey() + " , value :" + p1.getValue());
複製代碼
提供了一種包命名的方式
捕獲異常,異常的處理通常在文件,I/O,數據庫,這些地方存在各類不肯定的狀況,影響其中斷。
// 捕獲異常
try {
} catch (IndexOutOfBoundsException e) {
System.err.println("IndexOutOfBoundsException: " + e.getMessage());
} catch (IOException e) {
System.err.println("Caught IOException: " + e.getMessage());
}
//扔出異常
public Object pop() {
Object obj;
if (size == 0) {
throw new EmptyStackException();
}
obj = objectAt(size - 1);
setObjectAt(size - 1, null);
size--;
return obj;
}
複製代碼
I 表示輸入流, O 表示輸出流
I/O 流主要的方式
I/O採用不少設計模式,流是解決獲取數據的加載到內存緩存區問題 , Writer主要是解決流的序列化/存儲的問題
流的類型包括:
public boolean write(String sourceFileName, String targetFileName) throws IOException{
FileReader inputStream = null;
FileWriter outputStream = null;
try {
System.out.println("Now sourceFile :" +sourceFileName + " , targetFileName: "+ targetFileName);
inputStream = new FileReader(sourceFileName);
outputStream = new FileWriter(targetFileName);
int c;
while ((c = inputStream.read()) != -1) {
outputStream.write(c);
}
// return true;
} finally {
if (inputStream != null) {
inputStream.close();
}
if (outputStream != null) {
outputStream.close();
}
return false;
}
}
複製代碼
在併發編程中,有兩個基本的執行單元:進程和線程,一個進程有一個獨立的執行環境。一個進程一般具備一套完整的私有基本運行時資源; 特別是每一個進程都有本身的內存空間。因此處理大併發的事情,更多的是關係進程或者線程對服務器資源的壓力。包括CPU, 內存等
如今啓動的方式主要有兩種,一種是實現Runable接口,另外一種是繼承Thread
// 每一個線程都繼承了Runnable方法,每一個方法都考慮執行的效果
public class HelloRunnable implements Runnable {
public void run() {
System.out.println("Hello from a thread!");
}
public static void main(String args[]) {
(new Thread(new HelloRunnable())).start();
}
}
// 繼承Thread的方式
public class HelloThread extends Thread {
public void run() {
System.out.println("Hello from a thread!");
}
public static void main(String args[]) {
(new HelloThread()).start();
}
}
複製代碼
這個存在問題就是若是出現一個資源得到了鎖,另一個資源確一直沒有釋放鎖,就出現死鎖的狀況。 這樣就須要考慮資源的sleep和必要的中斷
public class Test {
public static void main(String[] args) {
ThreadPoolExecutor executor = new ThreadPoolExecutor(5, 10, 200, TimeUnit.MILLISECONDS,
new ArrayBlockingQueue<Runnable>(5));
for(int i=0;i <15 ; i++){
MyTask myTask = new MyTask(i);
executor.execute(myTask);
System.out.println("線程池中線程數目:"+executor.getPoolSize()+",隊列中等待執行的任務數目:"+
executor.getQueue().size()+",已執行玩別的任務數目:"+executor.getCompletedTaskCount());
}
executor.shutdown();
}
}
class MyTask implements Runnable {
private int taskNum;
public MyTask(int num) {
this.taskNum = num;
}
@Override
public void run() {
System.out.println("正在執行task "+taskNum);
try {
Thread.currentThread().sleep(4000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("task "+taskNum+"執行完畢");
}
}
複製代碼
支持對系統的屬性使用Key和value的方式crud。Properties繼承了java.util.Hashtable, 可使用其一些屬性特性
主要是Java的工具包獲取,Pattern.compile
Console console = System.console();
if (console == null) {
System.err.println("No console.");
System.exit(1);
}
while (true) {
Pattern pattern =
Pattern.compile(console.readLine("%nEnter your regex: "));
Matcher matcher =
pattern.matcher(console.readLine("Enter input string to search: "));
boolean found = false;
while (matcher.find()) {
console.format("I found the text" +
" \"%s\" starting at " +
"index %d and ending at index %d.%n",
matcher.group(),
matcher.start(),
matcher.end());
found = true;
}
if(!found){
console.format("No match found.%n");
}
}
複製代碼
集合拆分紅三種方式:List(數組列表) ,Set(不容許有重複元素的集合) ,Map(key和value 集合).Queue也是其中的一種方式
數據結構
算法
主要使用LocalTime 獲取時間的操做
DateTimeFormatter formatter =
DateTimeFormatter.ofPattern("MMM d yyyy");
LocalDate date = LocalDate.parse(input, formatter);
System.out.printf("%s%n", date);
複製代碼
反射機制本質就是根據地址塊,如對象,類,方法的地址塊去檢查或者修改其行爲。 主要的機制是java 虛擬機能夠經過命名空間+類名對內存塊的使用。 而且全部類/對象都有其自身的元數據包括public,private,屬性等狀況。
好的地方主要是能夠外部調用,如調試,開發工具,Spring的根據類名獲取對象,很差的地方主要是性能消耗大,而且可能會影響一些安全
經過運行時加載該類,而後找到這個類的方法和域(通常是解析字節碼得到到類相關的元數據),生成列表信息,最後動態加載該類。
網絡通常真正處理是專一於講應用層的數據傳遞到TCP 層,而後經過IP協議轉換
數據包的內容
Socket 通訊架構
Socket是解決數據兩種,一種是發數據,一種是接受數據,都是經過ip+端口的綁定,服務端是經過循環監聽客戶端的Socket數據
public void run() {
try {
BufferedReader br = new BufferedReader(new InputStreamReader(socket
.getInputStream()));
while (true) {
String msg = br.readLine();
if ("exit".equalsIgnoreCase(msg))
break;
System.out.println("("
+ socket.getInetAddress().getHostAddress() + ":"
+ socket.getPort() + "):" + msg);
}
br.close();
socket.close();
} catch (Exception e) {
e.printStackTrace();
}
}
複製代碼
Http通常有創建鏈接,發送請求和接受請求,最後關閉三個過程,若是很長時間才關閉通道,才關閉這算長鏈接,不然處理完就關閉,算短鏈接。
遠程方法調用這種方式適合內部機器的通訊,可是考慮到系統兼容性這種方式也不太好,最後通常會採用內部的http的通訊或者採用webserivce的方式。 主要是經過註冊了這個方法,而後遠程根據方法的參數和規範,來調用。 應該也是採用RPC的規範來走的。
方便的是能夠針對java語言搞分佈式計算跟語言綁定,能夠在虛擬機註冊列表裏面調用任何的註冊服務,可是這個依賴性太強了。後期的protobuf方式就是對現有的替代了。 - 動態代碼加載的優勢: 經過註冊類的方式來動態加載 - 能夠調用遠程接口和方法: 主要是經過RPC/TCP協議來處理 - 使用RMI建立分佈式應用程序 :能夠把 - 能夠創建分佈式應用: 計算引擎
)
主要是對於java的產品提供安全的認證,包括數字簽名
JDBC 主要解決了,JAVA提供的數據庫驅動API,這樣只要導入了對應的驅動文件,就能夠調用其服務哦。
public void connectToAndQueryDatabase(String username, String password) {
Connection con = DriverManager.getConnection(
"jdbc:myDriver:myDatabase",
username,
password);
Statement stmt = con.createStatement();
ResultSet rs = stmt.executeQuery("SELECT a, b, c FROM Table1");
while (rs.next()) {
int x = rs.getInt("a");
String s = rs.getString("b");
float f = rs.getFloat("c");
}
}
複製代碼
開發工具: (在bin/子目錄中)將幫助您開發,執行,調試和編寫以Java編程語言編寫的程序的工具和實用程序。有關更多信息,請參閱工具文檔。
運行環境: (在jre/子目錄中)由JDK使用的Java運行時環境(JRE)的實現。JRE包含一個Java虛擬機(JVM™),類庫和其餘支持執行用Java編程語言編寫的程序的文件。
額外的庫: (在lib/子目錄中)開發工具所需的其餘類庫和支持文件。
Java DB: (在db/子目錄中)Java DB,Oracle分佈的Apache Derby關係數據庫。有關更多信息,請參閱文檔。
C文件頭: (在include/子目錄中)使用Java本地接口,JVM工具接口和Java平臺的其餘功能支持本地代碼編程的頭文件。
源代碼:(In src.zip)構成Java核心API的全部類的Java編程語言源文件。使用:jar xvf src.zip
javac字節碼編譯器:
由如下文件組成的動態鏈接機制:
Java密碼擴展:
Java EE: 應用(瀏覽器/其餘Clent)發送http請求 -> 服務器(tomcat/nginx)-> Java CGI -> 請求JRE環境->調用/生成class文件->調用本地庫->輸出
是在前面RMI發展而來的。 支持知足企業級開發的方式。 可是標準一致很高,特別是EJB很是難上手,而且關聯的東西很是多。最後,Spring 以j2EE標準基礎上專門切入Bean管理也便是EJB的輕量版本(Model層),而後迅速佔領J2EE的開發框架重要地位,而且慢慢的把controller(Struct)解決了。甚至對V層也有必定的組件和擴展。 就出現了Spring MVC 框架。最後爲了解決EJB分佈式開發部署的成本問題,開發了Spring Boot 知足開發的需求。
主要是採用mvc的機制,最後經過Dao層去讀取數據庫
Maven 本質是解決jar包的統一管理的問題,這樣避免每一個項目以前還要下載大量的jar,而且有的時候還須要去找jar很麻煩的。 以前有相似的網站能夠下載到各類jar包你根據名字搜索就好,可是一個個下載不方便。 基於解決這類問題出現了maven. 其實每種語言都有相似的工具,如php 有Composer, python 有pip
Tomcat 是服務器主要的是監聽某個端口的服務器,Tomcat會自動讀取webapps 下的war文件。 而war文件Tomcat 會自動把java語言的代碼根據j2EE的規範來生成war包。
對於多個應用的部署,本地可使用{DOMAIN_NAME}/{app} 來管理多個項目,若是是線上,能夠採用Nginx +Tomcat的方式,Nginx 負責分發,Tomcat負責啓動多個服務來監聽Nginx的服務。
idea 和 Tomcat 關係: idea 使用Tomcat 把web代碼生成war包,而後瀏覽器能夠經過tomcat解析和處理這個war
github的wiki 有詳細的解釋
解決方式:把maven 類文件從新配置下,對於存在衝突的庫去掉,而後從新導入下
java.lang.NoSuchMethodError: org.springframework.util.ClassUtils.isPresent(Ljava/lang/String;Ljava/l
複製代碼
nginx: [error] invalid PID number "" in "/usr/local/var/run/nginx.pid"
複製代碼
## 解決 Mac 下配置環境變量在 ZSH 中無效的問題
在終端中輸入: cat ~/.zshrc 以此來查看 .zshrc 文件, 找到裏面的 「 # User configuration 「 部分. 能夠看到當前 zsh 支持的全部本地已配置環境變量.
## 輸入gradle home和path 目錄
GRADLE_HOME=/usr/local/Cellar/gradle/4.4;
export GRADLE_HOME
export PATH=$PATH:$GRADLE_HOME/bin
複製代碼
應該使用以下路徑進行設置:/usr/local/Cellar/gradle/2.4/libexec
,問題的關鍵就是路徑要有 libexec
複製代碼
後續還會持續更新JAVA的知識點,包括JAVA的分佈式架構,微服務,高併發的一些文章。 也但願你們有什麼好的建議和想法反饋給我。