基础

基本数据类型

名称 说明 默认值 最小值-最大值
byte byte 数据类型是8位、有符号的,以二进制补码表示的整数 0 -128(-2^7)/ 127(2^7-1)
short short 数据类型是 16 位、有符号的以二进制补码表示的整数 0 -32768(-2^15)/ 32767(2^15 - 1)
int int 数据类型是32位、有符号的以二进制补码表示的整数 0 -2,147,483,648(-2^31)
2,147,483,647(2^31 - 1)
long long 数据类型是 64 位、有符号的以二进制补码表示的整数; 0L -9,223,372,036,854,775,808(-2^63)
9,223,372,036,854,775,807(2^63 -1)
float float 数据类型是单精度、32位、符合IEEE 754标准的浮点数; 0.0f 必须加后缀
double double 数据类型是双精度、64 位、符合IEEE 754标准的浮点数 0.0d 默认小数类型
boolean boolean数据类型表示一位的信息 false true / false
char char类型是一个单一的 16 位 Unicode 字符 0 \u0000(0)
\uffff(65535)

位操作

  • &, 按位与
  • |, 按位或
  • ~, 按位非
  • ^, 按位异或
  • <<, 数位左移地位补零
  • , 有符号右移, 如果值为正,则在高位补0,如果值为负,则在高位补1

  • , 无符号右移,高位补零


作用域

  • 类级: 用static参数修饰,可以使用类直接访问
  • 实例对象级:对象实例化后可以访问
  • 方法级:定义方法中存在
  • 块级:”{ }”中存在

类型转换

自动拆装箱

  1. 所有的基本类型,都有对应的类类型 ,比如int对应的类是Integer ;通过=符号自动把 基本类型 转换为 类类型 就叫装箱(Integer it2 = 3),通过调用方法把类类型转换为基本类型就叫拆箱int i2 = it.intValue()<br />至于为什么要转换,因为基本类型转换为引用类型后,就可以new对象,从而调用包装类中封装好的方法、进行基本类型之间的转换,还有就是如果集合中想存放基本类型,泛型的限定类型只能是对应的包装类型。

强制类型转换

将一个类型强制转换成另外一个类型的过程被称为类型转换,但是这个类型转换会有一定的限制,只能在继承层次内进行类型转换,所以转换之前最好使用instanceof关键字进行一下判断。

Object obj = "asdasd";
System.out.println((Integer) obj); // 运行时报错
---------------------------------------------
List<String> list = new ArrayList<>();
list.add("test");
List<Integer> b = (List) (Object) list;
System.out.println(b.get(0)); // 不会报错,但是String类型在List中为Integer
System.out.println(b.get(0).getClass()); // 运行时报错
-------------------------------------------------
List<Object> list = new ArrayList<>();
list.add("test");
List<Integer> b = (List<Integer>) list; // 编译时报错

关键字

  • instanceof,用来测试一个对象是否为一个类的实例。其中 obj 为一个对象,Class 表示一个类或者一个接口,当 obj 为 Class 的对象,或者是其直接或间接子类,或者是其接口的实现类,结果result 都返回 true,否则返回false。原理可以简单理解为将obj强制类型转换为Class,如果类型转换不报错,就返回true。

    boolean result = obj instanceof Class
    
  • native,使用native关键字修饰的函数(方法),说明这个方法是原生函数,也就是这个方法是用C/C++语言实现的,并且被编译成了链接库,由Java去调用。

  • outLoop
    // 可以使用循环标签,在外层循环关键字上添加标签(相当于给外层循环起了一个名字),
    // 在需要跳出的地方( break $labelName 或 continue $labelNam)跳出或跳过外层循环。
    public class Test {
      public static void main(String[] args) {
          outLoop:
          for (int i=0; i<3; i++) {
              System.out.println("i:" + i);
              for (int j=0; j<3; j++) {
                  if (j == 1)
                      break outLoop;
                  System.out.println("J:" +j);
              }
          }
      }
    }
    

编程方法

面向对象

封装

  • 抽象与类
    • Interface: 定义接口,接口相当于一种约定,不要经常修改你的约定
    • Abstract Class:定义抽象类
    • Class:定义类属性,类方法,类初始化
  • 方法

    image.png

    • 公有的(public),在任何地方都可以访问该成员。
    • 受保护的(proteted),在同包的条件下的子类中可以被覆盖,而在不同包下的子类中只能被调用,是不能被覆盖的;并且声明该成员的包内部的任何类也可以访问这个成员。
    • 包级私有的(package-private), 声明该成员的包内部的任何类都可以访问这个成员
    • 私有的 (private)只有在声明该成员的顶层类内部才可以访问这个成员

继承

  • 类,抽象类可以继承于接口,抽象类,类;Java不支持不能多重继承类,抽象类;但是可以多重继承接口。
  • 一个单独的类,如果没有声明任何构造函数,那么系统会自动生成一个无参的构造函数,但是当前类如果存在有参数构造器,那么系统将不会自动生成无参数构造器。
  • 在继承关系中,当使用new一个类时,程序的执行顺序为:首先执行父类的构造函数方法,再执行自身的构造函数方法。因此子类的构造函数默认第一行隐式的语句super(),super()会访问父类中空参数的构造函数。当父类中没有空参数的构造函数时,子类必须手动通过super语句形式来指定要访问父类中的构造函数,而且必须放在构造函数第一行。
  • 在实现函数时要注意类的继承关系,比如函数参数限定类型为父类,那么可以传父类和其子类;如果限定参数为子类,那么只能传入子类而不能传入父类。

多态

  • Overriding :子类覆盖父类方法
  • Overloading :同一类中,方法通过参数的不同来表现多态性

枚举类

class Test {
    private static enum Season {
        SPRING,
        SUMMER,
        AUTUMN,
        WINTER,
    }

    public static void main(String[] args) {
        for (Season s : Season.values()) {
            System.out.println(s);
        }
    }
}

Comparable and Comparator

/**
 * Comparable and Comparator
 *
 */
import java.util.Collections;
import java.util.List;
import java.util.ArrayList;
import java.util.Comparator;

public class Character implements Comparable<Character> {
    int rank;

    public Character(int rank) {
        this.rank = rank;
    }

    public int compareTo(Character that) {
        if (this.rank < that.rank) {
            return -1;
        } else if (this.rank >that.rank) {
            return 1;
        }
        return 0;
    }

    public String toString() {
        return Integer.toString(rank);
    }
    public static void main(String[] args) {
        List<Character> characters = new ArrayList<Character>();
        for (int rank = 4; rank > 0; rank--) {
            Character c = new Character(rank);
            characters.add(c);
        }

        Comparator<Character> comparator = new Comparator<Character>() {
            @Override
            public int compare(Character c1, Character c2) {
                if (c1.rank < c2.rank) {
                    return -1;
                } else if (c1.rank > c2.rank) {
                    return 1;
                }
                return 0;
            }
        };
        Collections.sort(characters, comparator);
        // Collectiosn.sort() use compareTo method default
        //  Collections.sort(characters);
        for (Character c: characters) {
            System.out.println(c);
        }
    }
}

内部类

  • 静态内部类:指被声明为static的内部类,不能访问外部类的普通成员变量,只能访问外部类中的静态成员变量和静态方法。
  • 成员内部类:去掉关键字static就是成员内部类,可以自由的引用外部类的属性和方法。
  • 局部内部类:是指定义在一个代码块内的类,作用范围为其所在的代码块。局部类类似于局部变量一样,不能被public、protected、private以及static修饰,只能访问方法中定义为final类型的局部变量。
  • 匿名内部类:是一种没有类名的内部类,不使用关键字class、extends、implements,它必须继承其他类或实现其它接口

    • 匿名内部类不能有构造函数
    • 不能定义静态成员、方法和类
    • 不能是public、protected、private、static。
    • 只能创建匿名内部类的一个实例 ```java /** 非静态成员类

      • 可以访问外部类非静态属性和方法
      • 声明为为外部类的属性
      • 创建:new 外部类().new 内部类() */ public class Car { private String name;

      class Wheel { int count; public String toString() {

         return name;
      

      } }

      public static void main(String[] args) { Car chevrolet = new Car(); chevrolet.name = “Cruze”; // 所以其实例化必须建立在一个外部类对象的基础之上 Wheel wheel = chevrolet.new Wheel(); System.out.println(wheel); } }

/**

* 静态内部类
  • 静态内部类里面不可以访问外部类的实例属性和方法,可以访问外部类的私有静态成员外
  • 声明为外部类的属性
  • 创建:new 外部类.静态内部类(); */ public class Car { private String name; // 姓名

    static class Model {

    int serial;
    

    } }

/**

  • 匿名类
  • 声明在代码块中的类,声明一个类的同时实例化它,使代码更加简洁精练 */ public class Car { private String name; // 姓名

    public static void main(String[] args) {

         Wheel w = new Wheel(){
                public void run() {
            System.out.println("running");
        }
    

    }; } }

/**

  • 局部类
  • 声明在代码块中的类 */ public class Car { private String name; // 姓名

    public static void main(String[] args) {

        class Wheel {
        int count;
    }
    

    } }

<a name="Rk2Av"></a>
### 初始化块
[https://www.cnblogs.com/BlackStorm/p/5699965.html](https://www.cnblogs.com/BlackStorm/p/5699965.html)
<a name="yDQQ8"></a>
## 函数式编程

- [stream](https://colobu.com/2016/03/02/Java-Stream/#%E5%B9%B6%E8%A1%8C_Parallelism)
- [lambda](https://www.liaoxuefeng.com/article/974382480887712)
- [Function](https://blog.csdn.net/z834410038/article/details/77370785)

<a name="8045759e"></a>
## 泛型
Java中泛型是通过编译器擦除(erasure)的技术来实现的,仅在编译时检查泛型信息,编译之后擦除;所以Class字节码中是不包含泛型中的类型信息的,其中只包含泛型的原始类型也就是Object,获取的时候再强制类型转换为改类型。
```java
public class Test {  
    public static void main(String[] args) {  
        ArrayList<String> arrayList1 = new ArrayList<String>();  
        ArrayList<Integer> arrayList2 = new ArrayList<Integer>();  
        System.out.println(arrayList1.getClass() == arrayList2.getClass());  // return true 

          ArrayList<Integer> arrayList3 = new ArrayList<Integer>();  
        arrayList3.add(1);
        arrayList3.getClass().getMethod("add", Object.class).invoke(arrayList3, "asd");  
        for (int i=0; i<arrayList3.size(); i++) {  
            System.out.println(arrayList3.get(i));  
        } 
    }  
}

泛型是程序设计的一种特性,即参数化类型,允许程序员在强类型程序设计语言中编写代码时定义一些可变部分,那些部分在使用前必须作出指明。在Java中泛型有以下用法:

/**
 * 泛型类型用于类的定义中,被称为泛型类。
 * 说明:
 * 1) 泛型的类型参数只能是类类型,不能是简单类型。
 * 2) 定义的泛型类,不一定要传入泛型类型实参么,以下也是合法的
 *                Generic instance = Generic(false);
 *              instance.setKey(123);
 */        
public class Generic<T>{ 
    private T key;

    public Generic(T key) { 
        this.key = key;
    }

    public setKey(T key) {
        this.key = key;
    }

    public T getKey(){
        return key;
    }
}

/**
 * 泛型接口
 */
public interface Generator<T> {
    public T next();
}

/**
 * 泛型方法
 */
/**
 * 泛型方法的基本介绍
 * 说明:
 *     1)public 与 返回值中间<T>非常重要,可以理解为声明此方法为泛型方法。
 *     2)只有声明了<T>的方法才是泛型方法,泛型类中的使用了泛型的成员方法并不是泛型方法。
 *     3)<T>表明该方法将使用泛型类型T,此时才可以在方法中使用泛型类型T。
 *     4)与泛型类的定义一样,此处T可以随便写为任意标识,常见的如T、E、K、V等形式的参数常用于表示泛型
        5) 单独的T 代表一个类型 ,而 Class<T>代表这个类型所对应的类
             https://www.cnblogs.com/zhima-hu/p/7352555.html
 */
public <T> T genericMethod(Class<T> tClass)throws InstantiationException, 
IllegalAccessException {
        T instance = tClass.newInstance();
        return instance;
}

泛型通配符

/**
 * ? # 代表任意类型
 */
public void showKeyValue1(Generic<?> obj){
    System.out.println("泛型测试","key value is " + obj.getKey());
}

/**
 * T... # 代表泛型队列
 */
public <T> void printMsg( T... args){
    for(T t : args){
        System.out.println("泛型测试","t is " + t);
    }
}

# <? extends T> 泛型为T或者T的子类型
# <? super T>  #泛型为T或者T的父类型

泛型的使用: https://www.cnblogs.com/coprince/p/8603492.html
泛型的原理:https://www.cnblogs.com/xll1025/p/6489088.html

序列化

注解

注解其实就是代码中的特殊标记,这些标记可以在编译、类加载、运行时被读取,并执行相对应的处理。

元注解

  • @Target,表示该注解可以用于什么地方,就是注解使用的目标对象
    • @Target(ElementType.TYPE) :类、接口(包括注解类型)或enum声明。
    • @Target(ElementType.FIELD):字段、枚举的常量。
    • @Target(ElementType.METHOD):METHOD:方法声明。
    • @Target(ElementType.PARAMETER):方法参数声明。
    • @Target(ElementType.CONSTRUCTOR):构造器的声明。
    • @Target(ElementType.LOCAL_VARIABLE):局部变量声明。
    • @Target(ElementType.ANNOTATION_TYPE):注解类型声明。
    • @Target(ElementType.PACKAGE):包声明。
  • @Retention,表示需要在什么级别保存该注解信息,就是注解保存的策略
    • @Retention(RetentionPolicy.SOURCE):注解仅存在于源码中,注解在变为文件时生效
    • @Retention(RetentionPolicy.CLASS):注解会在class字节码文件中存在,直接在加载class文件时生效
    • @Retention(RetentionPolicy.RUNTIME):注解会在class字节码文件中存在,运行时可以通过反射获取到,注解在运行时生效
  • @Documented将此注解包含在Javadoc中
  • @Inherited允许子类继承父类中的注解,注解的继承是相对于类而言的,对于接口时无效的,注解只继承父类的类注解,不继承方法注解

    常见注解

    since Java5

  • @Overried 表明此方法重写父类方法,如果父类无此方法,则无法编译通过

  • @Deprecated 表示这个方法已经过期,不建议开发者使用
  • @Suppvisewarnings 忽略告警信息
  • @transient 不需要被序列化

since Java 7

  • @SafeVarargs 忽略任何使用参数为泛型变量的方法或构造函数调用产生的警告。

sice Java8

  • @FunctionalInterface - Java 8 开始支持,标识一个匿名函数或函数式接口
  • @Repeatable - Java 8 开始支持,标识某注解可以在同一个声明上使用多次

    自定义注解

    ```java /**
    • 注解中的属性定义类似interface中的方法
    • 格式是 返回值 属性名称()
    • 如果有默认值 格式为 返回值 属性名称() default 你的默认值。
    • 返回值 可以是基本数据类型,枚举类。 / import java.lang.annotation.;

@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface MyAnnotation {

String value() default "annotation";

int num();

ElementType type() default ElementType.FIELD;

}


**利用反射手动检查注解**
```java
public class DemoApplication {

    /**
     * 字符串判空校验
     * @author sunpy
     *
     */
    @Documented
    @Inherited
    @Target({ElementType.FIELD})
    @Retention(RetentionPolicy.RUNTIME)
    public @interface StringChecker {
        boolean isEmpty();
    }

    /**
     * 注解模型类
     * @author sunpy
     *
     */
    public static class User {

        @StringChecker(isEmpty=true)
        private String userName;

        public User(String userName) {
            this.userName = userName;
        }
    }

    public static class ValidatorResolver {
        public static <T> boolean validate(T t) throws Exception {
            Field[] fields = t.getClass().getDeclaredFields();
            for (Field field : fields) {
                field.setAccessible(true);
                StringChecker stringChecker = field.getAnnotation(StringChecker.class);

                if (stringChecker != null) {
                    if (stringChecker.isEmpty() != StringUtils.isEmpty((String) field.get(t)) ) {
                        return false;
                    }
                }
            }
            return true;
        }
    }


    public static void main(String[] args) {
//        SpringApplication.run(DemoApplication.class, args);

        User user = new User("");
        try {
            if (ValidatorResolver.validate(user)) {
                System.out.println("Check passed!");
            } else {
                System.out.println("Check failed!");
            }

        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
    }
}

使用ConstraintValidator进行注解的自动执行

public class DemoApplication {

    /**
     * 字符串判空校验
     * @author sunpy
     *
     */
    @Documented
    @Inherited
    @Target({ElementType.FIELD, ElementType.METHOD})
    @Retention(RetentionPolicy.RUNTIME)
    @Constraint(validatedBy = IsValidName.EmptyChecker.class)
    public @interface IsValidName {

        String message() default "Wrong";

        Class<?>[] groups() default {};

        Class<? extends Payload>[] payload() default{};

        class EmptyChecker implements ConstraintValidator<IsValidName, String> {

            @Override
            public void initialize(IsValidName arg0) {
            }

            @Override
            public boolean isValid(String value, ConstraintValidatorContext context) {
                if (StringUtils.isEmpty(value)) {
                    return false;
                }
                return true;
            }

        }
    }

    /**
     * 注解模型类
     * @author sunpy
     *
     */
    public static class User {

        @IsValidName
        private String userName;

        public User(String userName) {
            this.userName = userName;
        }

        public String getUserName() {
            return userName;
        }

    }

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);

        User user = new User("asdasd");
        user.getUserName();

    }

}


注解实现的原理**
https://docs.jboss.org/hibernate/validator/4.2/reference/zh-CN/html/validator- customconstraints.html#validator-customconstraints-constraintannotation
https://www.cnblogs.com/duan2/p/11704564.html
https://www.zhihu.com/question/24401191
https://www.cnblogs.com/strongmore/p/13282691.html