开发工具
IDEA 代码规范阿里p3c插件安装
Java基础
数据类型
装箱和拆箱
- 装箱:基本数据类型转换为包装器类型,比如将
int类型转换为Interger类型。 - 拆箱:包装器类型转化为基本数据类型,比如将
Interger类型转换为int类型。
| 基础类型 | 包装类 |
|---|---|
Integer派别:Integer、Short、Byte、Character、Long这几个类的valueOf方法的实现是类似的。Double派别:Double、Float的valueOf方法的实现是类似的。每次都返回不同的对象。
1.当一个基础数据类型与封装类进行==、+、-、*、/运算时,会将封装类进行拆箱,对基础数据类型进行运算。
2.装箱操作会创建对象,频繁的装箱操作会消耗许多内存,影响性能,所以可以避免装箱的时候应该尽量避免。
3.equals(Object o) 因为原equals方法中的参数类型是封装类型,所传入的参数类型(a)是原始数据类型,所以会自动对其装箱,反之,会对其进行拆箱。
4.当两种不同类型用==比较时,包装器类的需要拆箱,当同种类型用==比较时,会自动拆箱或者装箱。
数组
- 数组是用于存储同样数据类型的多个数据的一种数据结构。
- 数组长度不可变。
- 数组本身是一种引用类型。
数组定义
type[] arrayName;(推荐)
type arrayName[];
数组初始化
静态初始化:arrayName = new type[]{element1, element2, ......};
动态初始化:arrayName = new type[length];
可以使用foreach循环来遍历数组。
String类
- Java中的
String类首字母必须大写,因为它是一个类而不是一个内部的类型。 String类中存储字符仍然使用的是char类型的数组。String类被final关键字修饰,意味着String类不能被继承,并且它的成员方法都默认为final方法;字符串一旦创建就不能再修改。String类定义的字符串为字符串常量,是不可变的。Java会使用一个常量池机制存储字符串。- 如果要使用字符串变量,请使用
StringBuilder或者StringBuffer。 - 可以使用
+连接符来连接两个字符串。 - 使用
+连接符时,JVM会隐式创建StringBuilder对象,这种方式在大部分情况下并不会造成效率的损失,不过在进行大量循环拼接字符串时则需要注意。
面相对象
类
- 修饰符
classclass 类名 { } - 定义成员变量
【修饰符】 类型 变量名 【= 默认值】 - 定义方法
【修饰符】 返回值类型 方法名(形参列表){ }
访问控制
包
- 是一个类似文件夹的结构,用来避免类的重名,同一包下的类代表同一个逻辑下的类库单元。
- 在类的第一行中添加
package packageName来定义一个类属于哪个包。 - Java中,使用
import语句来动态引入一个你需要使用的Java包。 - 使用
import static语句来导入指定类的静态成员变量、静态方法。
一个.java文件中可以有很多类。不过注意以下几点:
1、public 权限的类只能有一个(也可以一个都没有,但最多只有1个)
2、这个.java文件的文件名必须是public类的类名(一般的情况下,这里放置main方法是程序的入口。)
3、若这个文件中没有public的类,则文件名随便是一个类的名字即可
4、用javac 编译这个.java文件的时候,它会给每一个类生成一个.class文件
继承
- Java使用
extends关键字来实现继承。 - Java使用
implements来实现一个接口。 - Java中,只可以继承一个父类。
- 子类可以重写父类的方法。Java中需要在子类中的重写方法上使用
@Override注解。子类使用super()方法调用父类的方法,包括构造方法。 - 修饰类当用
final去修饰一个类的时候,表示这个类不能被继承:- 被
final修饰的类,final类中的成员变量可以根据自己的实际需要设计为fianl。 final类中的成员方法都会被隐式的指定为final方法。在类的第一行中添加package packageName来定义一个类属于哪个包。
- 被
- 被
final修饰的方法不能被重写:- 一个类的
private方法会隐式的被指定为final方法。 - 如果父类中有
final修饰的方法,那么子类不能去重写。
- 一个类的
- 修饰成员变量:
- 必须初始化值。
- 被
fianl修饰的成员变量赋值,有两种方式:- 直接赋值
- 全部在构造方法中赋初值。
- 如果修饰的成员变量是基本类型,则表示这个变量的值不能改变。
- 如果修饰的成员变量是一个引用类型,则是说这个引用的地址的值不能修改,但是这个引用所指向的对象里面的内容还是可以改变的。
- 修饰局部变量:
- 必须要赋初始值,而且是只能初始化一次。
- 即为常量,不可修改。
抽象类
- 抽象类定义的格式:
abstract class 类名{ } - 抽象方法定义格式:
public abstract 返回值类型 方法名(参数); - 抽象类和抽象方法都要被
abstract修饰,抽象方法一定要定义在抽象类中。 - 抽象类不可以直接创建对象。
- 只有覆盖了抽象类中所有的抽象方法后,其子类才可以创建对象。否则该子类还是一个抽象类。
接口
- 接口是隐式抽象的,当声明一个接口的时候,不必使用
abstract关键字。 - 接口中每一个方法也是隐式抽象的,声明时同样不需要
abstract关键字。 - 接口中的方法都是公有的。
- 编译时自动为接口里定义的方法添加
public abstract修饰符。 - Java接口里的成员变量只能是
public static final共同修饰的,并且必须赋初始值,可以不写public static final,编译的时候会自动添加。
泛型 [参考]
泛型,即“参数化类型”。就是将类型由原来的具体的类型参数化,类似于方法中的变量参数,此时类型也定义成参数形式(可以称之为类型形参),然后在使用/调用时传入具体的类型(类型实参)。
一些常用的泛型类型变量:
E:元素(Element),多用于java集合框架
K:关键字(Key)
N:数字(Number)
T:类型(Type)
V:值(Value)
使用泛型的意义
-
适用于多种数据类型执行相同的代码(代码复用)
-
泛型中的类型在使用时指定,不需要强制类型转换(类型安全,编译器会检查类型)
泛型类
定义一个泛型类:public class GenericClass<T>{}
public class GenericClass<T> {
private T data;
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
public static void main(String[] args) {
GenericClass<String> genericClass=new GenericClass<>();
genericClass.setData("Generic Class");
System.out.println(genericClass.getData());
}
}
泛型接口
定义一个泛型接口:public interface GenericIntercace<T>{}
public interface GenericIntercace<T> {
T getData();
}
实现泛型接口方式一:public class ImplGenericInterface1<T> implements GenericIntercace<T>
public class ImplGenericInterface1<T> implements GenericIntercace<T> {
private T data;
private void setData(T data) {
this.data = data;
}
@Override
public T getData() {
return data;
}
public static void main(String[] args) {
ImplGenericInterface1<String> implGenericInterface1 = new ImplGenericInterface1<>();
implGenericInterface1.setData("Generic Interface1");
System.out.println(implGenericInterface1.getData());
}
}
实现泛型接口方式二:public class ImplGenericInterface2 implements GenericIntercace<String> {}
public class ImplGenericInterface2 implements GenericIntercace<String> {
@Override
public String getData() {
return "Generic Interface2";
}
public static void main(String[] args) {
ImplGenericInterface2 implGenericInterface2 = new ImplGenericInterface2();
System.out.println(implGenericInterface2.getData());
}
}
- 1.对于泛型参数是继承关系的泛型类之间是没有继承关系的
- 2.泛型类可以继承其它泛型类,例如: public class ArrayList extends AbstractList
- 3.泛型类的继承关系在使用中同样会受到泛型类型的影响
定义一个泛型方法
private static<T> TgenericAdd(T a, T b) {}
通配符类型
-
<? extends Parent>指定了泛型类型的上届/** * <? extend Parent> 指定了泛型类型的上界 */ public static void printExtends(GenericClass<? extends Fruit> genericClass){ System.out.println(genericClass.getData().getColor()); }? extends X表示类型的上界,类型参数是X的子类,那么可以肯定的说,get方法返回的一定是个X(不管是X或者X的子类)编译器是可以确定知道的。但是set方法只知道传入的是个X,至于具体是X的那个子类,不知道。- 总结:主要用于安全地访问数据,可以访问X及其子类型,并且不能写入非null的数据。
-
<? super Child>指定了泛型类型的下届/** * <? super Child> 指定了泛型类型的下界 */ public static void printSuper(GenericClass<? super Apple> genericClass){ System.out.println(genericClass.getData()); }? super X表示类型的下界,类型参数是X的超类(包括X本身),那么可以肯定的说,get方法返回的一定是个X的超类,那么到底是哪个超类?不知道,但是可以肯定的说,Object一定是它的超类,所以get方法返回Object。对于set方法来说,编译器不知道它需要的确切类型,但是X和X的子类可以安全的转型为X。- 总结:主要用于安全地写入数据,可以写入X及其子类型。
-
<?>指定了没有限制的泛型类型/** * <?> 指定了没有限定的通配符 */ public static void printNonLimit(GenericClass<?> genericClass){ System.out.println(genericClass.getData()); }
Java lambda表达式
Java lambda表达式主要作用是代替匿名内部类的繁琐语法。由三部分组成:
- 输入:->前面的部分,即被()包围的部分。此处只有一个输入参数,实际上输入是可以有多个的,如两个参数时写法:(a, b);当然也可以没有输入,此时直接就可以是()。
- 函数体:->后面的部分,即被{}包围的部分;可以是一段代码。
- 输出:函数式编程可以没有返回值,也可以有返回值。如果有返回值时,需要代码段的最后一句通过return的方式返回对应的值。
Consumer c = (o)->{
System.out.println(o);
}
Java 的lambda表达式使用的是一种叫做函数式接口的东西,函数式接口需要满足两个条件:
- 使用@FunctionalInterface注解修饰。
- 接口中智能包含一个方法。(default方法和static方法除外) 例如:
@FunctionalInterface
interface A {
void abc();
default void def(){
......
}
如果lambda表达式的代码块只有一条代码,则可以使用方法引用和构造器引用。
- 方法引用: 如果我们要实现接口的方法与另一个方法A类似,(这里的类似是指参数类型与返回值部分相同),我们直接声明A方法即可。也就是,不再使用lambda表达式的标准形式,改用高级形式。无论是标准形式还是高级形式,都是lambda表达式的一种表现形式。
- 方法引用的语法: 对象::实例方法类::静态方法类::实例方法 Compare c = String::equals;
构造引用:构造引用的语法:类名::new
集合
Stream流
常用工具类/方法
Java并发与多线程
Java原理与调优
Spring与SpringMVC
SpringBoot实践
未完待续...