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的分布式架构,微服务,高并发的一些文章。 也但愿你们有什么好的建议和想法反馈给我。