Java 语法及知识架构笔记;

[TOC]

Java 基础学习

Core Java 书籍官网

泛型

  • 方法
    public <T> T tell(T t){
      return t;
    }
  • 数组
    public static void main(String[] args){
      String arr[] = {"java","web"};
      tell(arr);
    }   
    

public static viod tell(T arr[]){
for(int i=0;i<arr.length;i++){
System.out.println(arr[i]);
}
}


demo
```java
private <T> T getObject(Message msg, Class<T> c) {
        return (T) msg.getData().getParcelable(c.getSimpleName());
    }

现实案例:
RxSharePreference.java

@CheckResult @NonNull public <T> Preference<T> getObject(@NonNull String key,
                                                         @NonNull T defaultValue, @NonNull Preference.Converter<T> converter) {
    checkNotNull(key, "key == null");
    return new RealPreference<>(preferences, key, defaultValue,
                                new ConverterAdapter<>(converter), keyChanges);
}

FlowableConversionTest.java from Rxjava

public <R, O> O x(Function<Publisher<T>, O> operator) {
    return operator.apply(onSubscribe);
}

基本类型

数字

 //java7 以后数字可以加下划线
int b = 1_000_000;
int by = 0B1111_0100_0010; // 二进制
int x = 0xCAFE;//十六进制
int eight = 010; // 八进制

Float

float 4 字节 double 8 字节
3.14F or 3.14D 不写默认为double类型

System.out.println(2.0 - 1.1);
// ==> 0.8999999999999999 二进制无法表示 1/10

强转

 double x = 9.997;
int nx = (int) x; // nx = 9;
int nx2 = (int)Math.round(x); // nx2 = 10;

int y = 2;
y += 3.9; // y = 5;

常用转化

List<Object> list ;
Object[] listener = list.toArray();

List<Object> list = Arrays.asList(T... elements);

Security

异常

常见异常

  • ArithmeticException(算术异常)
  • ClassCastException (类转换异常)
  • IllegalArgumentException (非法参数异常)
  • IndexOutOfBoundsException (下标越界异常)
  • NullPointerException (空指针异常)
  • SecurityException (安全异常)

常用技巧

静态方法导入直接使用

import static java.lang.Math.*;

Annotation

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Test {} 

生命周期 Retention

  1. SOURCE: 在源码生效,不会被编译器编译进入class
  2. CLASS: class核源码生效,执行时会被vm忽略。未的注释Retention时以class为默认值。
  3. RUNTIME:

作用范围 Target

public enum ElementType {
    /**标明该注解可以用于类、接口(包括注解类型)或enum声明*/
    TYPE,

    /** 标明该注解可以用于字段(域)声明,包括enum实例 */
    FIELD,

    /** 标明该注解可以用于方法声明 */
    METHOD,

    /** 标明该注解可以用于参数声明 */
    PARAMETER,

    /** 标明注解可以用于构造函数声明 */
    CONSTRUCTOR,

    /** 标明注解可以用于局部变量声明 */
    LOCAL_VARIABLE,

    /** 标明注解可以用于注解声明(应用于另一个注解上)*/
    ANNOTATION_TYPE,

    /** 标明注解可以用于包声明 */
    PACKAGE,

    /**
     * 标明注解可以用于类型参数声明(1.8新加入)
     * @since 1.8
     */
    TYPE_PARAMETER,

    /**
     * 类型使用声明(1.8新加入)
     * @since 1.8
     */
    TYPE_USE
}

数据类型

package com.zejian.annotationdemo;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * Created by wuzejian on 2017/5/19.
 * 数据类型使用Demo
 */

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface Reference{
    boolean next() default false;
}

public @interface AnnotationElementDemo {
    //枚举类型
    enum Status {FIXED,NORMAL};

    //声明枚举
    Status status() default Status.FIXED;

    //布尔类型
    boolean showSupport() default false;

    //String类型
    String name()default "";

    //class类型
    Class<?> testCase() default Void.class;

    //注解嵌套
    Reference reference() default @Reference(next=true);

    //数组类型
    long[] value();
}

默认赋值方式

默认会赋值给value方法

package com.zejian.annotationdemo;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * Created by zejian on 2017/5/20.
 * Blog : http://blog.csdn.net/javazejian [原文地址,请尊重原创]
 */
//定义注解
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface IntegerVaule{
    int value() default 0;
    String name() default "";
}

//使用注解
public class QuicklyWay {
    //当只想给value赋值时,可以使用以下快捷方式
    @IntegerVaule(20)
    public int age;

    //当name也需要赋值时必须采用key=value的方式赋值
    @IntegerVaule(value = 10000,name = "MONEY")
    public int money;
}

反射中的使用

查看 反射Annotation

常用注解

  1. @Documented 被修饰的注解会生成到javadoc中
  2. @Inherited 可以让注解被继承

enum

深入理解

public class EnumDemo {

    public static void main(String[] args){
        //直接引用
        Day day =Day.MONDAY;
    }

}
//定义枚举类型
enum Day {
    MONDAY, TUESDAY, WEDNESDAY,
    THURSDAY, FRIDAY, SATURDAY, SUNDAY
}

编译 javac EnumDemo.java

反编译

final class Day extends Enum
{
    //编译器为我们添加的静态的values()方法
    public static Day[] values()
    {
        return (Day[])$VALUES.clone();
    }
    //编译器为我们添加的静态的valueOf()方法,注意间接调用了Enum也类的valueOf方法
    public static Day valueOf(String s)
    {
        return (Day)Enum.valueOf(com/zejian/enumdemo/Day, s);
    }
    //私有构造函数
    private Day(String s, int i)
    {
        super(s, i);
    }
     //前面定义的7种枚举实例
    public static final Day MONDAY;
    public static final Day TUESDAY;
    public static final Day WEDNESDAY;
    public static final Day THURSDAY;
    public static final Day FRIDAY;
    public static final Day SATURDAY;
    public static final Day SUNDAY;
    private static final Day $VALUES[];

    static 
    {    
        //实例化枚举实例
        MONDAY = new Day("MONDAY", 0);
        TUESDAY = new Day("TUESDAY", 1);
        WEDNESDAY = new Day("WEDNESDAY", 2);
        THURSDAY = new Day("THURSDAY", 3);
        FRIDAY = new Day("FRIDAY", 4);
        SATURDAY = new Day("SATURDAY", 5);
        SUNDAY = new Day("SUNDAY", 6);
        $VALUES = (new Day[] {
            MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
        });
    }
}

反射

//正常使用
Day[] ds=Day.values();
//向上转型Enum
Enum e = Day.MONDAY;
//无法调用,没有此方法
//e.values();
//获取class对象引用
Class<?> clasz = e.getDeclaringClass();
if(clasz.isEnum()) {
    Day[] dsz = (Day[]) clasz.getEnumConstants();
    System.out.println("dsz:"+Arrays.toString(dsz));
}

/**
   输出结果:
   dsz:[MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY]
 */

覆盖enum类方法

package com.zejian.enumdemo;

/**
 * Created by zejian on 2017/5/8.
 * Blog : http://blog.csdn.net/javazejian [原文地址,请尊重原创]
 */
public enum Day2 {
    MONDAY("星期一"),
    TUESDAY("星期二"),
    WEDNESDAY("星期三"),
    THURSDAY("星期四"),
    FRIDAY("星期五"),
    SATURDAY("星期六"),
    SUNDAY("星期日");//记住要用分号结束

    private String desc;//中文描述

    /**
     * 私有构造,防止被外部调用
     * @param desc
     */
    private Day2(String desc){
        this.desc=desc;
    }

    /**
     * 覆盖
     * @return
     */
    @Override
    public String toString() {
        return desc;
    }


    public static void main(String[] args){
        for (Day2 day:Day2.values()) {
            System.out.println("name:"+day.name()+
                    ",desc:"+day.toString());
        }
    }

    /**
     输出结果:
     name:MONDAY,desc:星期一
     name:TUESDAY,desc:星期二
     name:WEDNESDAY,desc:星期三
     name:THURSDAY,desc:星期四
     name:FRIDAY,desc:星期五
     name:SATURDAY,desc:星期六
     name:SUNDAY,desc:星期日
     */
}

抽象方法

package com.zejian.enumdemo;

/**
 * Created by zejian on 2017/5/9.
 * Blog : http://blog.csdn.net/javazejian [原文地址,请尊重原创]
 */
public enum EnumDemo3 {

    FIRST{
        @Override
        public String getInfo() {
            return "FIRST TIME";
        }
    },
    SECOND{
        @Override
        public String getInfo() {
            return "SECOND TIME";
        }
    }

    ;

    /**
     * 定义抽象方法,每个枚举都要实现这个抽象方法
     * @return
     */
    public abstract String getInfo();

    //测试
    public static void main(String[] args){
        System.out.println("F:"+EnumDemo3.FIRST.getInfo());
        System.out.println("S:"+EnumDemo3.SECOND.getInfo());
        /**
         输出结果:
         F:FIRST TIME
         S:SECOND TIME
         */
    }
}

与接口

public enum Meal{
  APPETIZER(Food.Appetizer.class),
  MAINCOURSE(Food.MainCourse.class),
  DESSERT(Food.Dessert.class),
  COFFEE(Food.Coffee.class);
  private Food[] values;
  private Meal(Class<? extends Food> kind) {
    //通过class对象获取枚举实例
    values = kind.getEnumConstants();
  }
  public interface Food {
    enum Appetizer implements Food {
      SALAD, SOUP, SPRING_ROLLS;
    }
    enum MainCourse implements Food {
      LASAGNE, BURRITO, PAD_THAI,
      LENTILS, HUMMOUS, VINDALOO;
    }
    enum Dessert implements Food {
      TIRAMISU, GELATO, BLACK_FOREST_CAKE,
      FRUIT, CREME_CARAMEL;
    }
    enum Coffee implements Food {
      BLACK_COFFEE, DECAF_COFFEE, ESPRESSO,
      LATTE, CAPPUCCINO, TEA, HERB_TEA;
    }
  }
} 

枚举单利

/**
 * Created by wuzejian on 2017/5/9.
 * 枚举单利
 */
public enum  SingletonEnum {
    INSTANCE;
    private String name;
    public String getName(){
        return name;
    }
    public void setName(String name){
        this.name = name;
    }
}

EnumMap

 Map<Color,Integer> enumMap=new EnumMap<>(Color.class);
  • Key 值必须是枚举类型;
  • 使用EnumMap比HashMap会更加高效

EnumSet

  • 内部实现是位向量,直接存储和操作都是bit,因此EnumSet空间和时间性能都十分可观
  • EnumSet不允许使用 null 元素
  • 线程不安全

用法

创建一个具有指定元素类型的空EnumSet。
EnumSet<E>  noneOf(Class<E> elementType)       
//创建一个指定元素类型并包含所有枚举值的EnumSet
<E extends Enum<E>> EnumSet<E> allOf(Class<E> elementType)
// 创建一个包括枚举值中指定范围元素的EnumSet
<E extends Enum<E>> EnumSet<E> range(E from, E to)
// 初始集合包括指定集合的补集
<E extends Enum<E>> EnumSet<E> complementOf(EnumSet<E> s)
// 创建一个包括参数中所有元素的EnumSet
<E extends Enum<E>> EnumSet<E> of(E e)
<E extends Enum<E>> EnumSet<E> of( E... rest)
//创建一个包含参数容器中的所有元素的EnumSet
<E extends Enum<E>> EnumSet<E> copyOf(EnumSet<E> s)
<E extends Enum<E>> EnumSet<E> copyOf(Collection<E> c) // 不会copy重复的值

参考

  1. 深入理解Java枚举类型(enum)

反射

类的实例化

// 1. class
//获取Class对象的引用
clazz = Class.forName("study.reflect.User");
//第一种方法,实例化默认构造方法,User必须无参构造函数,否则将抛异常
User user = (User) clazz.newInstance();

// 2. public constructor 
//获取带String参数的public构造函数
Constructor cs1 =clazz.getConstructor(String.class);
//创建User
User user1= (User) cs1.newInstance("xiaolong");

// 3. private constructor 
Constructor cs2=clazz.getDeclaredConstructor(int.class,String.class);
//由于是private必须设置可访问
cs2.setAccessible(true);
//创建user对象
User user2= (User) cs2.newInstance(25,"lidakang");

//获取所有构造包含private
Constructor<?> cons[] = clazz.getDeclaredConstructors();
 //获取构造函数参数类型
Class<?> clazzs[] = cons[i].getParameterTypes();

Field类及方法

方法返回值 方法名称 方法说明
Field getDeclaredField(String name) (包含private修饰的)字段,不包括继承的字段
Field[] getDeclaredField() 获取Class对象所表示的类或接口的所有(包含private修饰的)字段,不包括继承的字段
Field getField(String name) 获取具有public修饰的字段,包含继承字段
Field[] getField() 获取修饰符为public的字段,包含继承字段

Field 常用操作

Class claz = Class.forName("study.reflect.TestReflect$Animal");
Field field = claz.getDeclaredField("name");
System.out.println("field-->"  + field.getType());
System.out.println("toGenericString-->" + field.toGenericString());
System.out.println("getDeclaringClass-->" + field.getDeclaringClass());

//study.reflect.TestReflect$Animal
//field-->class java.lang.String
//toGenericString-->private java.lang.String //study.reflect.TestReflect$Animal.name
//getDeclaringClass-->class study.reflect.TestReflect$Animal

Method类及用法

get Method

方法包含父类

//根据参数获取public的Method,包含继承自父类的方法
Method method = clazz.getMethod("draw",int.class,String.class);
//获取所有public的方法:包含父类
Method[] methods =clazz.getMethods();

方法不包含父类

//可以获取privat, 无法获取父类方法
Method method1 = clazz.getDeclaredMethod("drawCircle");
Method[] methods1=clazz.getDeclaredMethods();

Invoke

invoke(Object obj,Object... args)

Array

基本用法

//获取类型
Class<?> clazz = array.getClass().getComponentType();
// new 一个指定类型的Array
Object newArr = Array.newInstance(clazz, 15);
int co = Array.getLength(array);
//copy 赋值原数组到新数组
System.arraycopy(array, 0, newArr, 0, co);
// setter/getter
Array.set(newArr, 5/*pos*/, 3);
Array.get(newArra,5)

案例

Array的动态创建, 无效语句T[] a = new T[];

/**
  * 接收一个泛型数组,然后创建一个长度与接收的数组长度一样的泛型数组,
  * 并把接收的数组的元素复制到新创建的数组中,
  * 最后找出新数组中的最小元素,并打印出来
  * @param a
  * @param <T>
  */
 public  <T extends Comparable<T>> void min(T[] a) {
     //通过反射创建相同类型的数组
     T[] b = (T[]) Array.newInstance(a.getClass().getComponentType(), a.length);
     for (int i = 0; i < a.length; i++) {
         b[i] = a[i];
     }
     T min = null;
     boolean flag = true;
     for (int i = 0; i < b.length; i++) {
         if (flag) {
             min = b[i];
             flag = false;
         }
         if (b[i].compareTo(min) < 0) {
             min = b[i];
         }
     }
     System.out.println(min);
 }

反射Annotation

//指定类型是否存在
isAnnotationPresent(Class<? extends Annotation> annotationClass)
//得到指定的注解,没有返回null
clazz.getAnnoations(Depressed.class)
Annotation[] annote1 = getAnnotations()
//不包括父类
Annotation[] annote2 = getDeclaredAnnotations()

常用反射操作

 /** 
  *    修饰符、父类、实现的接口、注解相关 
  */

//获取修饰符,返回值可通过Modifier类进行解读
public native int getModifiers();
//获取父类,如果为Object,父类为null
public native Class<? super T> getSuperclass();
//对于类,为自己声明实现的所有接口,对于接口,为直接扩展的接口,不包括通过父类间接继承来的
public native Class<?>[] getInterfaces();
//自己声明的注解
public Annotation[] getDeclaredAnnotations();
//所有的注解,包括继承得到的
public Annotation[] getAnnotations();
//获取或检查指定类型的注解,包括继承得到的
public <A extends Annotation> A getAnnotation(Class<A> annotationClass);
public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass);

/** 
  *   内部类相关
  */
//获取所有的public的内部类和接口,包括从父类继承得到的
public Class<?>[] getClasses();
//获取自己声明的所有的内部类和接口
public Class<?>[] getDeclaredClasses();
//如果当前Class为内部类,获取声明该类的最外部的Class对象
public Class<?> getDeclaringClass();
//如果当前Class为内部类,获取直接包含该类的类
public Class<?> getEnclosingClass();
//如果当前Class为本地类或匿名内部类,返回包含它的方法
public Method getEnclosingMethod();

/** 
  *    Class对象类型判断相关
  */
//是否是数组
public native boolean isArray();  
//是否是基本类型
public native boolean isPrimitive();
//是否是接口
public native boolean isInterface();
//是否是枚举
public boolean isEnum();
//是否是注解
public boolean isAnnotation();
//是否是匿名内部类
public boolean isAnonymousClass();
//是否是成员类
public boolean isMemberClass();
//是否是本地类
public boolean isLocalClass(); 

enum 反射

public enum RunnableState{
  RUNNING, ERROR, DONE
}

  public static void main(String[] args) {
    Class clazz = RUNNING.getClass();
    Object[] enumConstants = clazz.getEnumConstants();
    for (Object enumConstant : enumConstants) {
      System.out.println(enumConstant);
    }
  }

//========= out ========
RUNNING
ERROR
DONE
//======================

关键字

  • assert false ; 在jvm的参数,参数是-ea或者-enableassertions 抛出java.lang.AssertionErro。增加错误信息,assert false : "这个异常没有性格";

Clone

浅度拷贝/深度拷贝

//1.直接强转只能克隆基本数据类型,原因是clone方法只是复制了相同的内存块
@Override
  protected Student clone() throws CloneNotSupportedException {
    return (Student) super.clone();
  }
//2.存在非基本数据类型的克隆方法
  @Override
  protected Student3 clone() throws CloneNotSupportedException {
    Student3 stu = (Student3) super.clone();
    stu.bag = bag.clone();
    return stu;
  }
//3.有些类是不能拷贝的如:StringBuffer没有重载clone()方法

读写操作

Java IO教程.英文

Java IO教程.中文

Apache Commons IO FileUtils

Apache Commons IO 教程

监控

监控工具

Java常用命令

javap -c PathForClazz.class 查看class汇编指令

常用工具

正则表达式

元字符

. 匹配除换行符以外的任意字符
\w 匹配字母或数字或下划线或汉字
\s 匹配任意的空白符,空格回车
\d 匹配数字
\b 匹配单词的开始或结束
^ 匹配字符串的开始
$ 匹配字符串的结束

Windows系统里面,每行结尾是“<回车><换行>”,即“\r\n”;

Mac系统里,每行结尾是“<回车>”,即“\r”。

Windows系统里面,每行结尾是“<回车><换行>”,即“\r\n”;

Mac系统里,每行结尾是“<回车>”,即“\r”。

而UNIX/Linux采用换行符LF表示下一行,即\n

苹果机(MAC OS系统)则采用回车符CR表示下一行,即\r

常用的限定符 重复

代码/语法 说明
* 重复零次或更多次
+ 重复一次或更多次
? 重复零次或一次
{n} 重复n次
{n,} 重复n次或更多次
{n,m} 重复n到m次

反义

代码/语法 说明
\W 匹配任意不是字母,数字,下划线,汉字的字符
\S 匹配任意不是空白符的字符
\D 匹配任意非数字的字符
\B 匹配不是单词开头或结束的位置
[^x] 匹配除了x以外的任意字符
[^aeiou] 匹配除了aeiou这几个字母以外的任意字符

后向引用

  • JAVA 正则表达式 (超详细)

  • 正则表达式30分钟入门教程

  • Ratifier 集中了Android验证的库,列如:

     Mobile Number: /^(+\d{1,3}[- ]?)?\d{10}$/
     Email Address: /^([a-z0-9_.-]+)@([\da-z.-]+).([a-z.]{2,6})$/
     URL: /^(https?://)?([\da-z.-]+).([a-z.]{2,6})([/\w .-])/?$/
     IP Address:/^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/

正则表达式30分钟入门教程笔记

简单的白话翻译

白话 正则翻译
精确地查找hi这个单词 \bhi\b
hi后面不远处跟着一个Lucy \bhi\b.*\bLucy\b
以0开头,然后是两个数字,然后是一个连字号“-”,最后是8个数字 0\d{2}-\d{8}
QQ号必须为5位到12位数字 ^\d{5,12}$
匹配deerchao.net deerchao\.net
匹配C:\Windows C:\\Windows
匹配Windows后面跟1个或更多数字 Windows\d+
匹配一行的第一个单词 ^\w+
匹配任何一个英文元音字母 [aeiou]
匹配标点符号(.或?或!) [.?!]
\S+ 匹配不包含空白符的字符串
<a[^>]+> 用尖括号括起来的以a开头的字符串
\b(\w+)\b\s+\1\b 匹配重复的单词,像go go

复杂的阅读理解
| 正则 | 翻译 |
| :———————————————————: | :————–: |
|0\d{2}-\d{8}| 0\d{3}-\d{7}|匹配两种以连字号分隔的电话号码:一种是三位区号,8位本地号(如010-12345678),一种是4位区号,7位本地号(0376-2233445)|
|(0\d{2})[- ]?\d{8}| 0\d{2}[- ]?\d{8}|匹配3位区号的电话号码,其中区号可以用小括号括起来,也可以不用,区号与本地号间可以用连字号或空格间隔,也可以没有间隔|
|(\d{1,3}.){3}\d{1,3}|简单的IP地址匹配|
|\b\w+(?=ing\b)|以ing结尾的单词的前面部分(除了ing以外的部分),如查找I’m singing while you’re dancing.时,它会匹配sing和danc|
|(?<=\bre)\w+\b|以re开头的单词的后半部分(除了re以外的部分),例如在查找reading a book时,它匹配ading|
|((?<=\d)\d{3})+\b|
234567890*进行查找时结果是234567890|
|(?<=\s)\d+(?=\s)|以空白符间隔的数字(再次强调,不包括这些空白符)|
|\d{3}(?!\d)|三位数字,而且这三位数字的后面不能是数字|
|\b((?!abc)\w)+\b|不包含连续字符串abc的单词|
|(?<![a-z])\d{7}|前面不是小写字母的七位数字|
|(?<=<(\w+)>).
(?=</\1>)|匹配不包含属性的简单HTML标签内里的内容|

匹配IP地址:((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)

正则表达式——详细讲解平衡组

JavaDoc

实战案例

  1. Class Level

    /**
    * Hero is the main entity we'll be using to . . .
    * 
    * Please see the {@link com.baeldung.javadoc.Person} class for true identity
    * @author Captain America
    * 
    */
    public class SuperHero extends Person {
        // fields and methods
    }
  2. Field Level

    /**
     * The public name of a hero that is common knowledge
     */
    private String heroName;
  3. Method Level

    /**
     * Factory for {@linkplain Call calls} // 连接到其他类的说明
     * <h3>OkHttpClients should be shared</h3> //设置字体大小
     * {@link #newBuilder()} // 连接本地方法
     * {@link ExecutorService#shutdown shutdown()} // 连接其他类的方法
     * <p>This is a simple description of the method. . . // <p> 能实现换行功能
     * <a href="http://www.supermanisthegreatest.com">Superman!</a>
     * </p>
     * //代码块
     * <pre>   {@code
     *   // The singleton HTTP client.
     *   public final OkHttpClient client = new OkHttpClient.Builder()
     *       .addInterceptor(new HttpLoggingInterceptor())
     *       .cache(new Cache(cacheDir, cacheSize))
     *       .build();
     * }</pre>
     * {@code String}  //{@code text} 将文本标记为code 一般在Javadoc中只要涉及到类名或者方法名,都需要使用@code进行标记
      * <ul><li>{@code toffset} is negative. // 无符号列表
      * <li>{@code ooffset} is negative.
      * <li>{@code toffset+len} is greater than the length of this
      * {@code String} object.
      * <li>{@code ooffset+len} is greater than the length of the other
      * </ul>
     * @param incomingDamage the amount of incoming damage
     * @return the amount of health hero has after attack
     * @see <a href="http://www.link_to_jira/HERO-402">HERO-402</a>
     * @since 1.0
     * @version 版本
     */
    public int successfullyAttacked(int incomingDamage) {
        // do things
        return 0;
    }
  4. javadoc -d doc src\* 生成

  5. maven plugin mvn javadoc:javadoc

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-javadoc-plugin</artifactId>
                <version>3.0.0</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
                <tags>
                ...
                </tags>
            </plugin>
        </plugins>
    </build>
  6. Custom TAG javadoc -tag location:a:“Notable Locations:”-d doc src*``

    /**
     * This is an example...
     * @location New York
     * @returns blah blah
     */

    @location 替换成 Notable Locations:

    above maven plugin

    ...
    <tags>
        <tag>
            <name>location</name>
            <placement>a</placement>
            <head>Notable Places:</head>
        </tag> 
    </tags>
    ...

参考

Java 高级

JVM

1. ClassLoader 介绍

1.1 结束一个JVM的生命周期方式

1.2 类加载的三中方式

  1. 验证 -> 确保被加载类的正确性
  2. 准备 -> 为类的静态变量分配内存,将其初始化为默认值
  3. 解析 -> 把类中的符号引用转换为直接应用
  4. 初始化 -> 为类的静态变量赋予正确的初始化值

1.4 主动使用

除了以下六个,其余的都是被动使用,不会导致类的初始化

  1. new, 直接使用
  2. 访问某个类或者接口的静态变量,或者对静态变量进行赋值操作
    1. 访问类的静态变量会初始化class
  3. 调用静态方法
  4. 反射某个类
  5. 初始化一个子类
  6. 启动类,比如:java HelloWorld

1.5 被动使用

三种易错的被动使用

  1. 通过子类访问父类的static变量,不会导致子类的初始化
  2. 定义引用数组,不会初始化类
  3. final修饰的常量会在编译期间放到常量池中,不会初始化类
  4. final修饰的复杂类型,在编译期间无法计算得出,会初始化类

2. 类加载详解

2.1 加载类的方式

  1. 本地磁盘加载
  2. 内存直接加载
  3. 网络加载 URLClassLoader
  4. 从zip,jar等归档文件中加载.class文件
  5. 数据库中提取.class文件
  6. 动态编译

2.2 JVM内存简介

2018070215085731

  1. Execution engine功能:执行classes中的指令
  2. Native interface组件:与native libraries交互
  3. Runtime Data Area组件也就是JVM内存

2.2.1 Program Counter Register

2.2.2 Java Virtual Machine Stacks

2.2.3 Heap Memory

2.2.4 Method Area

2.2.5 Run-time Constant Pool

2.2.6 Native Method Stack

Class and Object in the Memory

1556803701272

创建对象的过程

1556804652176

3. 类的连接详解

3.1 验证

字节流中包含的信息符合虚拟机的要求,并不会损害到JVM自身安全

  • 文件格式验证
    • 魔术因子是否正确,0xCAFEBABE
    • 主从版本号是否符合当前虚拟机
    • 常量池中的常量类型是不是支持
  • 元素数据验证
  • 字节码验证
  • 字符号引用验证

3.2 准备阶段

  1. 初始值

3.3 解析

3.4 初始化

4. 类的初始化详解

5. 类加载器(JDK自带)详细介绍

1556806319483

JVM自带的几种加载器

根(Bootstrap)

  1. 负责加载核心类库,如java.lang.*等。
  2. 指定加载目录为System.getProperty("sun.boot.class.path")
  3. 没有继承ClassLoader类,没有父加载器;

扩展(Extension)类加载器

  1. 父加载器为Bootstrap;
  2. 指定加载目录为System.getProperty(“java.ext.dirs”),或者从jdk/jre/lib/ext 中加载

系统(System)类加载器

  1. 父家加载器为Extension;
  2. 指定加载目录为classpath或System.getProperty(“java.class.path”)指定目录
  3. 用户自定义类默认加载器

6. 类加载的父委托机制

  1. 先有父加载,父加载不到再由儿子孙子加载,Tomcat的加载器机制和JVM正好相反
  2. 父加载器和子加载器其实是一种包装关系,或者包含关系
  3. 优点: 能提高系统的安全性,在此机制下,用户自定义的类加载器不可能加载应该有父加载器加载的可靠类,防止恶意的代码代替父加载的可靠代码

7. 命名空间&运行时包

命名空间

每个类的加载器都有子的命名空间,命名空间由该加载器及其所有父加载器所加载的类组成。

1556852278628

运行时包

  1. 父类家加载器看不到子类加载器加载的类
  2. 不同命名空间下的类加载器之间的类互相不可访问

8. 创建自定义类加载器

9. 类的卸载

JVM中的Class只有满足以下三个条件,才能被GC回收,也就是该Class被卸载(unload):

  1. 该类所有的实例都已经被GC。

  2. 加载该类的ClassLoader实例已经被GC。

  3. 该类的java.lang.Class对象没有任何地方被引用。

GC的时机我们是不可以控的,那么同样的我们对于Class的卸载也是不可控的。

10. 自定义解密加密类加载器

11. 线程上下文加载器

SPI(Service Provider Interface)

is an API intended to be implemented or extended by a third party. It can be used to enable framework extension and replaceable components. for example jdbc, jndi,jms in the rt.jar.

The reason for ContextLoader:

rt.jar was loaded by BootClassLoader, but the implementation is loaded by AppClassLoader

JDBC example

com.mysql.jdbc.Driver

static{
    try{
        java.sql.DriverManager.registerDriver(new Driver());
    }catch(SQLException E){
        throw new RuntimeException("Cann't register driver!");
    }
}

Custom Context Class Loader

Thread.currentThread().setContextClassLoader(new MyClassLoader());
System.out.println(Thread.currentThread().getContextClassLoader());

12. 关于JVM类加载器的总结

附录

Java实战笔记

class声明为final的好处

  • 不会被重载
    • Vm产生更快codes
    • 防止自己改的代码影响到客户
  • 多线程使用安全
  • 针对Final的优化
    • Jvm和Application有针对final的缓存
    • Final keyword allows JVM to optimized method, variable or class.
    • jit能够避免使用虚函数表

结论:能用final尽量使用final

运行Java代码

Exmaple.java

#编译Java代码成.class
javac Exmaple.java 
# 运行.class文件
java -cp . Example
#后台运行
nohup java -cp . Exmaple 
# 查看后台运行日志
tail -f nohup.out

问题解决

学习资源

很好的深入Java基层系列

  1. 深入理解Java类型信息(Class对象)与反射机制
  2. 深入理解Java枚举类型(enum)
  3. 深入理解Java注解类型(@Annotation)
  4. 深入理解Java并发之synchronized实现原理
  5. 深入理解Java内存模型(JMM)及volatile关键字
  6. 深入理解Java类加载器(ClassLoader)

附录

javase 11 API 官方文档搜索

工具

Expresso 正则工具

http://www.ultrapico.com/ExpressoDownload.htm