1、强烈建议,不使用char类型
那么,到底为什么java里不推荐使用char类型呢?其实,1个java的char字符并不完全等于一个unicode的字符。char采用的UCS-2编码,是一种淘汰的UTF-16编码,编码方式最多有65536种,远远少于当今Unicode拥有11万字符的需求。java只好对后来新增的Unicode字符用2个char拼出1个Unicode字符。导致String中char的数量不等于unicode字符的数量。
然而,大家都知道,char在Oracle中,是固定宽度的字符串类型(即所谓的定长字符串类型),长度不够的就会自动使用空格补全。因此,在一些特殊的查询中,就会导致一些问题,而且这种问题还是很隐蔽的,很难被开发人员发现。一旦发现问题的所在,就意味着数据结构需要变更,可想而知,这是多么大的灾难啊。
2、final修饰的常量
用关键字final指示常量,关键字final表示这个变量只能被赋值一次,一旦被赋值,就不能再更改了,习惯上,常量名使用全大写。
如果经常希望某个常量可以在一个类中的多个方法中使用,通常将这些常量称为类常量,使用关键字static final修饰。
3、检查字符串是否为null也不为空串
if (str != null && str.length() != 0) {
System.out.println("字符串不为空");
} else {
System.out.println("字符串为空");
}
4、“==”与“equals”的区别
“==”:
1)用于比较值类型(int、float、boolean等)
2)用于比较引用类型,如果两个对象的引用地址相同,则返回true
“equals”:
1)用于比较引用类型,默认情况下与“==”的返回结果相同
2)由开发者覆写此方法,自己定义逻辑。比如常见的String类对此方法的覆写,覆写过后,即使两个对象的引用地址不同,返回结果仍然可以相同
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = value.length;
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}
5、Objects.equals(A,B)与A.equals(B)比较
查看源码,会发现Objects.equals(A,B)方法在比较之前,会先检查A是否为空,避免程序报空指针的异常
public static boolean equals(Object a, Object b) {
return (a == b) || (a != null && a.equals(b));
}
6、LocalDate与Date
如果只想对日期进行操作,而不对时间点进行操作,建议使用LocalDate类,而不是Date类,前者拥有更多的操作方法,后者的方法已经逐渐被废弃
7、在将父类转换成子类之前,应该使用instanceof进行检查
Object obj = "test";
if (obj instanceof String) {
String str = (String) obj;
System.out.println(str);
}
尽量避免进行强制类型转换,可以通过重新设计父类的方式,来避免这种操作
8、public class 与 class
public class是公共类的意思,public是访问修饰符。java规定一个类文件中,public修饰的class只有一个,并且类名必须和这个类的文件名一样,所以一个类文件中可以有多个类,但由public修饰的类只能有一个
备注:protected、private很少会用于修饰类
9、public、protected、private修饰符
这里说的修饰,主要是对类中的方法、域等进行修饰
在说明这四个关键字之前,我想就class之间的关系做一个简单的定义,对于继承自己的class,可以认为他们都是自己的子女,而对于和自己一个目录(同一个包路径)下的class,认为都是自己的朋友。
1、public:public表明该数据成员、成员函数是对所有用户开放的,所有用户都可以直接进行调用
2、private:private表示私有,私有的意思就是除了class自己之外,任何人都不可以直接使用,私有财产神圣不可侵犯嘛,即便是子女,朋友,都不可以使用。
3、protected:protected对于子女、朋友来说,就是public的,可以*使用,没有任何限制,而对于其他的外部class,protected就变成private。
作用域 | 当前类 | 同一个package | 子孙类 | 其他package |
public | √ | √ | √ | √ |
protected | √ | √ | √ | × |
private | √ | × | × | × |
default | √ | √ | × | × |
注:不写时默认为friendly
10、Integer.valueOf()与Integer.parseInt()
Integer.parseInt()把String类型转换为int类型
Integer.valueOf()把String类型转换为Integer对象
11、格式化输出
String message = String.format("Hello,%s.Next year,you'll be %d", "jyy", );
System.out.println(message);
System.out.printf("Hello,%s.Next year,you'll be %d", "jyy", );
转换符,不需要特意的记忆,使用的时候,再进行查找
12、switch语句
如果在case分支语句的末尾没有break语句,那么就会接着执行下一个case语句,这种情况相当危险,为此,我们程序中从不使用switch语句。
13、不定长数组-ArrayList
//初始化
ArrayList<Car> arrayList = new ArrayList<>();
//添加
arrayList.add(new Car(1001, "奔驰", 200));
arrayList.add(new Car(1002, "宝马", 300));
//在中间位置添加
arrayList.add(1, new Car(1003, "保时捷", 500));
//修改
arrayList.set(0, new Car(1001, "奥迪", 400));
//查询
Car c = arrayList.get(0);
System.out.println(c.toString());
//删除
arrayList.remove(2);
//查询长度
arrayList.size();
//转数组
Car[] cars = new Car[arrayList.size()];
arrayList.toArray(cars);
对数组实施插入和删除元素的操作其效率很低。对于小型数组来说,这一点也不必担心。但如果数组存储的元素数比较多,又经常在中间位置插入、删除元素,就应该考虑使用链表来处理了。
14、类修饰符
只有内部类可以是私有类(private),而常规类只可以具有包可见性(默认),或公有可见性(public)
15、受检异常和非受检异常(运行时异常)
Error类和Exception类都是继承Throwable类,RunTimeException继承Exception类。
1、受检异常,编译会报错,开发时就必须处理。非受检异常,编译不会报错,一般是开发的漏洞或者失误,由人主导,尽量避免。
2、RunTimeException类、Error类及其子类,属于非受检异常,如:NullPointerException、IndexOutOfBoundsException等。
除了上面之外的异常属于受检异常。
备注:Error类是系统中的错误,只能通过修改程序才能修正。一般是指与虚拟机相关的问题,如系统崩溃,虚拟机错误,内存空间不足,方法调用栈溢等。对于这类错误的导致的应用程序中断,仅靠程序本身无法恢复和和预防,遇到这样的错误,建议让程序终止。
3、如果方法里面抛出了受检异常,那么方法的签名必须throws这个异常,调用方也会被强制try-catch处理这个异常,这是编译级别的限制
如果是RunTimeException或者Error类及其子类那就是非受检的,这种异常在方法内抛出,不需要在方法的签名上throws
如何使用?
1、如果抛出的异常是可恢复的,同时我们也期望API的调用者捕获异常进行恢复处理,那么我们应该使用受检异常。受检异常会强迫API的使用者截获异常并恢复处理,或者进行声明继续抛出。
2、虽然受检异常是Java语言一项很好的特性,它强迫程序员处理异常,大大增强程序的可靠性。但是过分的使用受检异常会使API使用非常不方便,调用者必须在catch块中处理所有的受检异常,或者调用者必须声明抛出这些受检异常。
总而言之,对于可恢复的情况,使用受检异常;如果不清楚是否可能恢复,则最好使用未受检异常。
16、String的特别之处
String虽然是引用类型,但是它可以不使用new关键字进行创建,而且创建的对象保存在常量池中,而不是堆中。如:String A ="abc";如果常量池中已经存在"abc",就会直接把引用传递给A,而不是生成新的"abc"。如果使用String A = new String("abc"),每一次调用都会在堆中生成新的对象。
17、try-with-resources
语法糖:建议将try-finally
替换为try-with-resources
Connections, streams, files, and other classes that implement the Closeable interface or its super-interface, AutoCloseable, needs to be closed after use.
Further, that close call must be made in a finally block otherwise an exception could keep the call from being made. Preferably,
when class implements AutoCloseable, resource should be created using "try-with-resources" pattern and will be closed automatically.
Java库中有很多资源需要手动关闭,比如InputStream、OutputStream、java.sql.Connection等等。在此之前,通常是使用try-finally
的方式关闭资源;Java7之后,推出了try-with-resources
声明来替代之前的方式。 try-with-resources
声明要求其中定义的变量实现 AutoCloseable 接口,这样系统可以自动调用它们的close方法,从而替代了finally中关闭资源的功能。
举个栗子,按照原本try-catch-finally
的写法:
OutputStream outputStream = null;
FileInputStream fileInputStream = null;
try {
outputStream = response.getOutputStream();
fileInputStream = new FileInputStream(xmlPath);
byte[] b = new byte[1024];
int i;
while ((i = fileInputStream.read(b)) > 0) {
outputStream.write(b, 0, i);
}
outputStream.flush();
} catch (Exception e) {
logger.error(e.toString());
} finally {
if (outputStream != null) {
outputStream.close();
}
if (fileInputStream != null) {
fileInputStream.close();
}
}
替换成try-with-resources之后:
try (FileInputStream fileInputStream = new FileInputStream(xmlPath); OutputStream outputStream = response.getOutputStream()) {
byte[] b = new byte[1024];
int i;
while ((i = fileInputStream.read(b)) > 0) {
outputStream.write(b, 0, i);
}
outputStream.flush();
} catch (Exception e) {
logger.error(e.toString());
}
try-with-resources
将会自动关闭try()
中的资源,并且将先关闭后声明的资源。
18、@Suppresswarnings
@Suppresswarnings注解,可以消除代码中的警告,可以作用于类、属性、方法、方法入参、构造函数和方法的局部变量。
关键字 | 描述 |
all | to suppress all warnings (将方法块里面所有的warning都取消) |
cast | to suppress warnings relative to cast operations |
dep-ann | to suppress warnings relative to deprecated annotation (取消对已弃用的注释的警告) |
deprecation | to suppress warnings relative to deprecation( 使用了不赞成使用的类或方法时的警告) |
fallthrough |
to suppress warnings relative to missing breaks in switch statements(当 Switch 程序块直接通往下一种情况而没有 Break 时的警告。)
|
finally | to suppress warnings relative to finally block that don’t return(任何 finally 子句不能正常完成时的警告) |
hiding | to suppress warnings relative to locals that hide variable(取消对隐藏变量的警告) |
incomplete-switch |
to suppress warnings relative to missing entries in a switch statement (enum case) (取消对switch里面缺少case条目的警告)
|
null | to suppress warnings relative to null analysis(取消对null分析的警告) |
nls | to suppress warnings relative to non-nls string literals (取消对 non-nls字符串的警告) |
path | 在类路径、源文件路径等中有不存在的路径时的警告。 |
rawtypes |
to suppress warnings relative to un-specific types when using generics on class params (当在类参数中使用非特定的泛型时,取消警告)
|
restriction | to suppress warnings relative to usage of discouraged or forbidden references (取消使用不鼓励或禁止的引用的警告) |
serial |
to suppress warnings relative to missing serialVersionUID field for a serializable class(当在可序列化的类上缺少 serialVersionUID 定义时的警告。)
|
static-access |
to suppress warnings relative to incorrect static access(取消不正常的静态访问的警告)
|
synthetic-access | to suppress warnings relative to unoptimized access from inner classes |
unchecked |
to suppress warnings relative to unchecked operations(执行了未检查的转换时的警告,例如当使用集合时没有用泛型 (Generics) 来指定集合保存的类型。)
|
unqualified-field-access | to suppress warnings relative to field access unqualified |
unused | to suppress warnings relative to unused code (将未使用的方法的warning取消) |
WeakerAccess | 禁止“Access can be private”的警告 |