基础
基本数据类型
名称 | 说明 | 默认值 | 最小值-最大值 |
---|---|---|---|
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参数修饰,可以使用类直接访问
- 实例对象级:对象实例化后可以访问
- 方法级:定义方法中存在
- 块级:”{ }”中存在
类型转换
自动拆装箱
所有的基本类型,都有对应的类类型 ,比如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:定义类属性,类方法,类初始化
方法
- 公有的(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
序列化
- 使用FastJson进行序列化
注解
注解其实就是代码中的特殊标记,这些标记可以在编译、类加载、运行时被读取,并执行相对应的处理。
元注解
- @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