Java只允许单继承,所有类最终的根类是Object;
protected允许子类访问父类的字段和方法;
子类的构造方法可以通过**super()**调用父类的构造方法;
可以安全地向上转型为更抽象的类型;
可以强制向下转型,最好借助instanceof判断;
final修饰符有多种作用:
(1)final修饰的方法可以阻止被覆写;
(2)final修饰的class可以阻止被继承;
(3)final修饰的field必须在创建对象时初始化,随后不可修改。
定义了抽象方法的类是抽象类,不能被实例化;
抽象方法对应于c++的纯虚函数,关键字为abstract.
从抽象类继承的子类,若不实现抽象方法,则子类也是抽象类
如果一个抽象类没有字段,所有方法全部都是抽象方法,则可以改写为接口
接口比抽象类更抽象
Java内建的package机制是为了避免class命名冲突;
JDK的核心类使用java.lang包,编译器会自动导入;
JDK的其它常用类定义在java.util.,java.math.,java.text.*,……;
包名推荐使用倒置的域名,例如org.apache
位于同一个包的类,可以访问包作用域的字段和方法。不用public、protected、private修饰的字段和方法就是包作用域
定义为public的field、method可以被其他类访问,前提是首先有访问class的权限;
包作用域是指一个类允许访问同一个package的没有public、private修饰的class,以及没有public、protected、private修饰的字段和方法。
一个.java文件只能包含一个public类,但可以包含多个非public类。如果有public类,文件名必须和public类的名字相同。
StringBuilder是可变对象,用来高效拼接字符串;
StringBuilder可以支持链式操作,实现链式操作的关键是返回实例本身;
StringBuffer是StringBuilder的线程安全版本,现在很少使用。
Java核心库提供的包装类型可以把基本类型包装为class;
自动装箱和自动拆箱都是在编译期完成的(JDK>=1.5);
装箱和拆箱会影响执行效率,且拆箱时可能发生NullPointerException;
包装类型的比较必须使用equals();
整数和浮点数的包装类型都继承自Number;
所有的包装类型都是不变类,因此,一旦创建了Integer对象,该对象就是不变的。
从Java 14开始,提供新的record关键字,可以非常方便地定义Data Class:
使用record定义的是不变类;
可以编写Compact Constructor对参数进行验证;
可以定义静态方法。
BigInteger用于表示任意大小的整数;
BigInteger是不变类,并且继承自Number;
将BigInteger转换成基本类型时可使用longValueExact()等方法保证结果准确。
Java提供的常用工具类有:
Math:数学计算
Random:生成伪随机数
SecureRandom:生成安全的随机数
只要是方法声明的Checked Exception,不在调用层捕获,也必须在更高的调用层捕获。所有未捕获的异常,最终也必须在main()方法中捕获,不会出现漏写try的情况。这是由编译器保证的。main()方法也是最后捕获Exception的机会。
如果是测试代码,上面的写法就略显麻烦。如果不想写任何try代码,可以直接把main()方法定义为throws Exception:
public class Main {
public static void main(String[] args) throws Exception {
byte[] bs = toGBK("中文");
System.out.println(Arrays.toString(bs));
}
static byte[] toGBK(String s) throws UnsupportedEncodingException {
// 用指定编码转换String为byte[]:
return s.getBytes("GBK");
}
}
Java的异常是class,并且从Throwable继承;
Error是无需捕获的严重错误,Exception是应该捕获的可处理的错误;
RuntimeException无需强制捕获,非RuntimeException(Checked Exception)需强制捕获,或者用throws声明;
不推荐捕获了异常但不进行任何处理。
Commons Logging是使用最广泛的日志模块;
Commons Logging可以自动检测并使用其他日志模块。
通过Commons Logging实现日志,不需要修改代码即可使用Log4j;
使用Log4j只需要把log4j2.xml和相关jar放入classpath;
如果要更换Log4j,只需要移除log4j2.xml和相关jar;
只有扩展Log4j时,才需要引用Log4j的接口(例如,将日志加密写入数据库的功能,需要自己开发)。
JVM为每个加载的class及interface创建了对应的Class实例来保存class及interface的所有信息;
获取一个class对应的Class实例后,就可以获取该class的所有信息;
通过Class实例获取class信息的方法称为反射(Reflection);
JVM总是动态加载class,可以在运行期根据条件来控制加载class。
所有interface类型的变量总是通过某个实例向上转型并赋值给接口类型变量的:有没有可能不编写实现类,直接在运行期创建某个interface的实例呢?
这是可能的,因为Java标准库提供了一种动态代理(Dynamic Proxy)的机制:可以在运行期动态创建某个interface的实例。
使用类似 extends Number>通配符作为方法参数时表示:
即一句话总结:使用extends通配符表示可以读,不能写。
使用类似定义泛型类时表示:
对比extends和super通配符
我们再回顾一下extends通配符。作为方法参数, extends T>类型和 super T>类型的区别在于:
hashmap中依据key的hash值来确定value存储位置,所以一定要重写hashCode方法,而重写equals方法,是为了解决hash冲突,如果两个key的hash值相同,就会调用equals方法,比较key值是否相同,在存储时:如果equals结果相同就覆盖更新value值,如果不同就用List他们都存储起来。在取出来是:如果equals结果相同就返回当前value值,如果不同就遍历List中下一个元素。即要key与hash同时匹配才会认为是同一个key。
JDK中源码:if(e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k)))){ops;}
treemap使用自定义的compare方法存放在红黑树中,无需重写equals和hashCode。关于treemap能不能存放重复键的问题参照这篇博客:
https://blog.csdn.net/u010698072/article/details/55255073?utm_medium=distribute.pc_aggpage_search_result.none-task-blog-2aggregatepagefirst_rank_ecpm_v1~rank_v31_ecpm-6-55255073-null-null.pc_agg_new_rank&utm_term=treemap%E7%9A%84%E5%80%BC%E5%8F%AF%E4%BB%A5%E9%87%8D%E5%A4%8D%E5%90%97&spm=1000.2123.3001.4430