根据多种资料,整理了一些 Java 相关的知识内容。
1. Java基础
1.1 Java入门
Java语言特点?
- 简单易学;面向对象(封装、继承、多态);平台无关性(一次编译,到处运行);可靠性;安全性;多线程;网络编程;编译与解释并存。
JVM、JDK、JRE都是什么?
-
JVM:JVM是运行Java字节码的虚拟机,根据系统有不同版本。
- Java通过将源代码转换为字节码,解决了传统解释型语言效率低的问题,编译一次
.java文件
生成的字节码文件.class文件
可以在各种环境下解释运行。 - 由于字节码解释运行也比较慢,因此后面还引入了
JIT
编译器,运行时编译,将常用部分的字节码转换为机器码保存。 - 由于
JIT
也比较慢,后面引入了AOT
编译模式,直接将字节码转换为机器码,但质量不如JIT
。
- Java通过将源代码转换为字节码,解决了传统解释型语言效率低的问题,编译一次
-
JDK:JDK是Java开发环境,是功能齐全的Java SDK。
- JDK拥有JRE的一切,还拥有编译器
javac
,工具(如javadoc和jdb)。能够创建和编译程序。 - API:应用程序接口,提供功能。
- SDK:软件开发工具包,提供开发基础。
- JDK拥有JRE的一切,还拥有编译器
-
JRE:JRE是Java运行时环境,是运行已编译Java程序所需的所有内容的集合。
- 包括JVM、Java类库、Java命令和其他基础构件。
- 但JRE不能用于创建新程序。
- 只运行不开发通常只需要JRE,但有时候也需要JDK,如需要JSP部署Web应用程序,服务器将JSP转换为
Java Servlet
,需要用JDK编译Java Servlet
。
Oracle JDK和OpenJDK有啥区别?
- OpenJDK是一个开源参考模型,Oracle JDK是OpenJDK的一个实现。
- Oracle JDK更稳定、更高性能。
Java和C++有啥异同?
- 都是面向对象语言,支持封装、继承、多态。
- Java不提供指针来直接访问内存。
- Java类单继承,C++类可以多继承,Java接口可以多继承。
- Java有自动内存管理垃圾回收机制
GC
。 - Java字符串结尾不需要
\0
,因为字符串相当于对象,有长度属性。
Java主类是什么?
- Java主类是程序执行的入口。
- Java应用程序中,主类是包含main()方法的类,不一定是public类。
- Java小程序中,主类是继承自系统类
JApplet
或JApplet的子类
,一定是public类。(?)
Java包和Javax有啥关系?
- 两者指的是一个东西,都是Java API的组成部分。
为啥说Java语言编译与解释并存?
- 编译是一次性翻译,解释是逐行解释。
- Java先编译生成字节码,再解释成机器码,因此两者并存。
1.2 Java语法
字符型和字符串型的区别?
-
字符型是单引号围起来的一个字符,占2字节空间,可以参与运算。
-
字符串型是双引号围起来的若干字符。
Java注释有哪些?
- 单行注释,多行注释,文档注释。
- 好的代码是最好的注释。
标识符和关键字的区别?
- 标识符就是一个名字。
- 关键字是系统赋予特殊含义的标识符。
Java关键字有哪些(需要注意的)?
- 访问控制
- 类、方法和变量修饰符:extends、final、implements、interface、strictfp、synchronized、transient、volatile。
- 程序控制:instanceof、switch、case、default。
- 错误处理:finally。
- 包相关
- 基本类型
- 变量引用:super、this、void。
- 保留字:goto、const。
自增自减运算符是啥?
- ++、--在前面就先变化再赋值,在后面就是先赋值再变化。
泛型是啥?
-
泛型是参数化类型,将操作的数据类型作为一个参数。
-
泛型包括泛型类、泛型接口、泛型方法。
类型擦除是啥?
- 类型擦除是Java编译期间,所有泛型信息会被擦除,不会在字节码中出现。
- 类型擦除造成编译时检测可能会存在问题。
常用通配符有啥?
- ?:不确定类型。
- E:元素。
- K:键。
- V:值。
- T:具体类型。
==和equals()的区别是啥?
- ==判断的是是否是同一对象,即内存地址。
- equals()没有覆盖,和==等价,也是判断是否是同一对象,即内存地址。
- equals()覆盖了,一般都是
equals()和hashcode()有啥关系?
- 两个对象相等,则hashcode()获取的哈希码一定相等。
- 两个对象哈希码相等,两个对象不一定相等。
- 因此,equals()修改了,hashcode()为了保证满足上面两个性质,也要修改。
1.3 基本数据类型
自动装箱拆箱是啥?
- 装箱:将基本类型用对应的引用类型包装起来。
- 拆箱:将包装类型转换为基本数据类型。
常量池是啥?
-
常量池是包装类默认创建的缓存数据。
-
Byte、Short、Integer、Long默认创建了[-128, 127]的缓存数据。
-
Character创建了[0, 127]的缓存数据。
-
Boolean创建了True和False。
-
Float、Double没有常量池。
1.4 方法(函数)
Java为啥只有值传递?
- Java采用按值调用(call by value),方法得到的是参数值的拷贝,不能修改参数变量的内容。
- 另一种方法是按引用调用(call by reference),可以修改参数变量内容。
- Java不能修改基本数据类型参数,但可以修改对象类型的内部参数,如数组内部,但不能修改对象。
重载和重写有啥区别?
- 重载:一个方法,根据输入数据不同,进行不同处理。
- 重写:子类继承并覆盖父类方法。
- 重载发生在编译期,重写发生在运行期。
- 重写要求范围相同或更小。
- 重写要求返回、方法、参数都要相同。
- 重写要求private、final、static的方法和构造方法不能重写。
浅拷贝和深拷贝有啥区别?
- 浅拷贝:对对引用数据类型进行引用传递。
- 深拷贝:对引用数据类型,新建一个对象,并复制内容。
- 两者对基本数据类型都是值传递。
2. Java面向对象
2.1 类和对象
面向过程和面向对象有啥区别?
- 面向过程:性能更高,不需要实例化类。
- 面向对象:易复用、易维护、易扩展。具有封装、继承、多态的特性,能开发高复用低耦合的系统。
- Java性能低于C和它半编译的特性也相关。
构造器能否被重写和重载?
- 构造器不能重写,但可以重载。
没有参数没有内容的构造方法有啥作用?
- 执行子类构造方法时,如果子类构造方法没有用super指定特定的父类构造方法,就会默认调用没有参数和没有内容的父类构造方法,帮助子类初始化。因此,父类需要构造这样的方法。
成员变量和局部变量有啥区别?
- 成员变量:属于类,可以用类修饰符和static修饰符,存在于堆内存,生命周期与对象相同。
- 局部变量:存在于栈内存,生命周期与方法相同。
- 用static修饰的成员变量是类变量,没有则是实例变量。
- 成员变量和局部变量都能用final修饰符。
为啥要写无参构造方法?
- 没有写构造方法,Java会自动添加无参构造方法。但写了构造方法,Java就不会添加无参构造方法。这时要是不手动添加无参方法,容易出错。因此需要写无参构造方法。
构造方法有啥特性?
- 名字与类名相同。
- 可以有修饰符,但不用void修饰符,没有返回值。
- 构造时自动调用。
对象相等和引用相等,有啥区别?
- 对象相等:内存存放内容相等。
- 引用相等:内存地址相等。
封装是啥?
- 封装是把一个对象的状态信息隐藏在对象内部,外部不能直接访问,但可以通过提供的方法进行访问。
继承是啥?
- 继承是用已存在的类的定义作为基础,构建新类。
- 通过继承,可以提高代码重用、程序可维护性、节省时间、提高效率。
多态是啥?
-
多态是同一个对象根据不同实例执行不同操作,具体体现在
父类引用指向子类对象
。 -
引用调用哪个类的方法,只有程序运行期才能确定。
-
多态不能调用只有子类有,父类没有的方法。
2.3 修饰符
为啥静态方法不能调用非静态成员?
- 静态方法可以
不通过对象进行调用
,因此不能调用其他非静态变量和非静态变量成员。
静态方法和实例方法有啥不同?
- 静态方法:可以用
类名.方法名
或`对象名.方法名
两种方式调用。只能访问静态成员。 - 实例方法:只能用
对象名.方法名
方式调用。可以访问任何成员。
2.4 接口和抽象类
接口和抽象类有啥不同?
- 接口:JDK7中,接口只能有常量变量和抽象方法。JDK8中,接口可以有默认方法和静态方法。JDK9中,接口可以有私有方法和私有静态方法。接口变量只能有static和final变量。接口是一种行为规范。
- 抽象类:抽象类可以有非抽象方法。抽象类是一种模板设计。
2.5 其他重要知识点
String、StringBuffer和StringBuilder有啥区别?
- String:对象不可变,因为用final修饰字符数组存储内容。常量,所以线程安全。
- StringBuffer:对象可变,没有用final修饰字符数组。没有同步锁,线程不安全。
- StringBuilder:对象可变,没有用final修饰字符数组。有同步锁,线程安全。
- 少量数据String合适,单线程大量数据StringBuilder合适,多线程大量数据StringBuffer合适。
Object类有啥方法?
-
Object类是所有类的父类。主要包含11个方法。
public final native Class> getClass()//native方法,用于返回当前运行时对象的Class对象,使用了final关键字修饰,故不允许子类重写。 public native int hashCode() //native方法,用于返回对象的哈希码,主要使用在哈希表中,比如JDK中的HashMap。 public boolean equals(Object obj)//用于比较2个对象的内存地址是否相等,String类对该方法进行了重写用户比较字符串的值是否相等。 protected native Object clone() throws CloneNotSupportedException//naitive方法,用于创建并返回当前对象的一份拷贝。一般情况下,对于任何对象 x,表达式 x.clone() != x 为true,x.clone().getClass() == x.getClass() 为true。Object本身没有实现Cloneable接口,所以不重写clone方法并且进行调用的话会发生CloneNotSupportedException异常。 public String toString()//返回类的名字@实例的哈希码的16进制的字符串。建议Object所有的子类都重写这个方法。 public final native void notify()//native方法,并且不能重写。唤醒一个在此对象监视器上等待的线程(监视器相当于就是锁的概念)。如果有多个线程在等待只会任意唤醒一个。 public final native void notifyAll()//native方法,并且不能重写。跟notify一样,唯一的区别就是会唤醒在此对象监视器上等待的所有线程,而不是一个线程。 public final native void wait(long timeout) throws InterruptedException//native方法,并且不能重写。暂停线程的执行。注意:sleep方法没有释放锁,而wait方法释放了锁 。timeout是等待时间。 public final void wait(long timeout, int nanos) throws InterruptedException//多了nanos参数,这个参数表示额外时间(以毫微秒为单位,范围是 0-999999)。 所以超时的时间还需要加上nanos毫秒。 public final void wait() throws InterruptedException//跟之前的2个wait方法一样,只不过该方法一直等待,没有超时时间这个概念 protected void finalize() throws Throwable { }//实例被垃圾回收器回收的时候触发的操作
transient关键字有啥用?
- transient用于避免序列化,即存储在内存中。transient只能修饰变量,不能修饰类和方法。
获取键盘输入有啥好方法?
-
Scanner:
-
BufferedReader:
3. Java核心技术
3.1 反射机制
Java反射机制是啥?
- 反射机制是,运行期间,类可以获取所有实时属性和方法,对象可以调用所有实时属性和方法。
- 反射机制属于动态编译,运行时确定类型,绑定对象。
- 反射机制能够提高代码灵活性。
- 反射机制相当于一系列解释操作,性能降低。反射机制还可能造成安全问题。
反射机制用在啥地方?
- 模块化开发,调用对应字节码应用了反射机制。
- 动态代理设计模式应用了反射机制。
- 框架如Spring、Hibernate等应用了反射机制。具体而言,Spring的IOC创建对象和AOP都应用了反射机制。
3.2 异常
Java异常类结构是啥?
- java.lang包内的Throwable类是所有异常类的祖先。
- Throwable有两个子类:Error错误子类,Exception异常子类。
- Error子类:存放程序无法处理的错误,主要是JVM故障。
- Exception子类:存放程序错误,主要是程序设计存在问题。
Throwable类有啥常用方法?
-
常用方法包括:
try-catch-finally是啥套路?
- try:用于捕获异常,后面可跟若干个catch块,可以跟finally块。如果没有catch块,则要跟一个finally块。
- catch:用于处理try捕获到的异常。
- finally:无论是否捕获到,finally都会执行。如果catch中有return,finally会接着return执行,还可以修改return值。
finally啥时候不执行?
- finally第一句出现异常。
- 前面的代码System.exit(int)关闭程序。
- 程序所在线程死亡。
- CPU关闭。
try-with-resources又是啥套路?
-
try-with-resources是Java 7后推荐使用的方法,比try-catch-finally能捕获更多有用的信息。
-
try-with-resources中,任何catch或finally块在声明的资源关闭后运行。多个资源需要关闭时可以用分号分隔开。
3.3 多线程
程序、进程和线程有啥关系?
- 程序:程序是含有指令和数据的文件,存储在存储设备中,是静态的代码。
- 进程:进程是程序的一次执行过程,是系统运行程序的基本单位,是动态的。进程按顺序执行指令,占用一定系统资源。进程相互独立。
- 线程:线程是比进程更小的单位,由进程创建,多个线程共享一个内存空间和系统资源。线程切换影响比进程小。
线程有啥基本状态?
-
线程包括6种基本状态:
-
NEW
-> start() ->READY
-> time ->RUNNING
-> wait() ->WAITING
->TIME_WAITING
->BLOCKED
-> run() ->TERMINATED
3.4 文件与I\O流
Java中的I\O流都有啥?
- I\O流包括:输入流、输出流;字节流、字符流;节点流、处理流。
- I\O流类包括:InputStream/Reader、OutputStream/Writer,分别是输入流、输出流基类,前后分别是字节流和字符流。
字节流和字符流有啥区别?
- 字节流:更适合传递媒体文件
- 字符流:更适合传递文字。需要字节转换步骤,耗时易出错,不适合处理媒体文件。
BIO、NIO、AIO有啥区别?
- BIO:同步阻塞IO模型,数据读写必须阻塞在一个线程内。适用于低负载、低并发应用程序。
- NIO:同步非阻塞IO模型。适用于高负载、高并发应用程序。
- AIO:NIO的改进版,异步非阻塞IO模型,但目前应用不广泛。
4. Java基础难点
4.1 Java基础
equals()为啥容易出错?
-
equals()容易抛出空指针异常。如:
改正:
-
使用java.util.Object.equals()可以有效避免抛出空指针异常。因为里面自带了前面字符串判断null逻辑。
-
可以用
==
和!=
来比较null值,不能用其他方法。null == null 判定是true。
整型包装类对象怎么比较?
- 必须用equals()方法。而且包装类方法已经被重写过,比较的是值而不是内存地址。
BigDecimal有啥用?
-
BigDecimal主要防止浮点数运算中的精度丢失。
-
BigDecimal主要方法:
- equals()。
- compareTo():-1、0、1分别表示小于、等于、大于。
- setScale():保留几位小数及保留规则。
-
阿里巴巴开发手册要求,BigDecimal必须用String类型赋值,或用valueOf()方法赋值。绝不能用double赋值。
- new BigDecimal("0.1");
- BigDecimal.valueOf(0.1);
基本数据类型和包装数据类型啥时候用?
- 基本数据类型:局部变量。
- 包装数据类型:
POJO类
(简单实体类)属性、RPC方法
(远程过程调用)的返回值和参数。 - 包装数据类型的null和0是不同含义,而基本数据类型不能体现null的含义,所以要注意区别。
4.2 集合
Arrays.asList()方法咋用?
-
Arrays.asList()可以将list数组转换为ArrayList数组,但不能实现add()、remove()、clear()功能。
-
传入对象必须是对象数组,也就是包装类数组。
咋将数组转换为ArrayList?
-
最简便的方法:
List list = new ArrayList<>(Arrays.asList("a", "b", "c"))
-
Java8 Stream方法:
Integer [] myArray = { 1, 2, 3 }; List myList = Arrays.stream(myArray).collect(Collectors.toList()); //基本类型也可以实现转换(依赖boxed的装箱操作) int [] myArray2 = { 1, 2, 3 }; List myList = Arrays.stream(myArray2).boxed().collect(Collectors.toList());
-
Guava方法:
- 对于不可变集合,可以使用
ImmutableList
类及其of()
与copyOf()
工厂方法(参数不能为空):
List
il = ImmutableList.of("string", "elements"); // from varargs List il = ImmutableList.copyOf(aStringArray); // from array - 对于可变集合,可以使用
Lists
类及其newArrayList()
工厂方法:
List
l1 = Lists.newArrayList(anotherListOrCollection); // from collection List l2 = Lists.newArrayList(aStringArray); // from array List l3 = Lists.newArrayList("or", "string", "elements"); // from varargs - 对于不可变集合,可以使用
-
Java9 List.of()方法:
Integer[] array = {1, 2, 3}; List
list = List.of(array); System.out.println(list); /* [1, 2, 3] */ /* 不支持基本数据类型 */
Collection.toArray()方法咋用?
-
该方法是泛型方法,应该有参数。可以给数组的第一个值作为参数,这个参数的用处是说明返回值类型,如:
String [] s= new String[]{ "dog", "lazy", "a", "over", "jumps", "fox", "brown", "quick", "A" }; List
list = Arrays.asList(s); Collections.reverse(list); s = list.toArray(new String[0]);//没有指定类型的话会报错,String[0]用来说明返回值类型
for-each为啥不能进行remove/all操作?
-
只有迭代器能进行remove/all操作,其他遍历不能进行remove/all操作,否则会触发
fail-fast机制
,抛出ConcurrentModificationException
错误。 -
Java 8 后,可以用Collection.removeIf()方法进行remove:
List
list = new ArrayList<>(); for (int i = 1; i <= 10; ++i) { list.add(i); } list.removeIf(filter -> filter % 2 == 0); /* 删除list中的所有偶数 */ System.out.println(list); /* [1, 3, 5, 7, 9] */ -
迭代器remove操作,如:
5. 常用单词
Java 中一些常用单词。
- JDK:Java Development Kit:Java 开发工具包。
- JRE:Java Runtime Environment:Java 运行时环境。
- JVM:Java Virtual Machine:Java 虚拟机。
- bit:比特。
- byte:字节。
- compile:编译。
- Java SE:Java Standard Edition:Java 标准版。
- Java EE:Java Enterprise Edition:Java 企业版。
- Java ME:Java Micro Edition:Java 小型版。
- GC:Garbage Collection:垃圾收集机制。
- arithmetic:算数,算法。
- relational operator/database/expression:关系运算符,关系型数据库,关系表达式。
- util:utility:实用的,通用的。
- score:分数。
- avg:average:平均值。
- ArrayIndexOutOfBoundsException:数组下标越界异常。
- NullPointerException:空指针异常。
- actual parameter:实参。
- formal parameter:形参。
- command line parameter:命令行参数。
- OOP:Object Oriented Programming:面向对象编程。
- oriented:导向的。
- programming:编程。
- rectangle:矩形。
- variable:变量。
- statement:语句。
- arguments:参数。
- declare:声明。
- this:当前对象。
- constructor:构造函数,构造器。
- encapsulation:封装。
- pass by reference:按引用传递。
- pass by value:按值传递。
- override:覆盖。
- inherit:继承。
- instanceof:实例。
- casting, overcasting, downcasting:转型,向上转型,向下转型。
- ClassCastException:类型转换异常。
- polymorphism:多样性。
- dependency:依赖。
- association:关联。
- aggregation:聚合。
- composite:组合。
- generalization:泛化,继承。
- interface:接口。
- implements:实现。
- singleton:单例。
- proxy:代理人。
- annotation:注释。
- suppress:抑制。
- SuppressWarnings:抑制警告。
- anonymous:匿名的。
- ordinal:顺序的。
- retention:保留。
- metadata:元数据。
- RuntimeException:运行时异常。
- NumberFormatException:数字格式化异常。
- JavaBean:对象。
- parse:解析。
- trim:削减。
- substring:子串。
- split:分离。
- uppercase, lowercase:大小写。
- concat:合并数组或字符串。
- sqrt:square root:开平方。
- abs:取绝对值。
- pow:乘幂。
- ceil, floor, round:三种取整。
- date:日期。
- calendar:日历。
- format:格式化。
- wrapper:包装类。
- boxing:装箱。
- octal:八进制。
- hex:十六进制。
- decimal:小数的。
- equalsIgnoreCase:忽视大小写比较是否相等。
- current:当前的。
- remainder:余数。
- locale:区域。
- leap year:闰年。
- instant:立即的。
- offset:偏移。
- temporal:时间的。
- concurrent:并发的。
- parallel:并行的。
- ConcurrentModificationException:并发修改异常。
- property:属性。
- generic:泛化。
- wildcard:通配符。
- canonical:规范化。
- suffix:后缀,下标。
- preffix:前缀。
- buffer:缓冲。
- serialize:串行化,序列化。
- transient:暂时的,瞬态的。
- charset:字符集。
- UID:Unique IDentifier:唯一标识符。
- RandomAccessFile:支持随机访问文件。
- allocate:分配。
- flip:翻转。
- rewind:回滚。
- interrupted:中断的。
- resume:恢复。
- IP:Internet Protocal:互联网协议。
- TCP:Transmission Control Protocal:传输控制协议。
- UDP:User Datagram Protocal:用户数据报协议。
- datagram:数据报。
- HTTP:Hyper Text Transport Protocal:超文本传输协议。
- URL:Uniform Resource Locator:全球资源定位器。
- invoke:调用。
- new instance:新实例。
- primitive type:base data type:primary data type:atomic data type:基本数据类型。
- reference type:引用数据类型。
- generic superclass / interface:泛化父类 / 接口。
- getDeclaredMethod:返回泛化的 Method 对象。
- supplier:供应商。
- predicate:断言。
- unary:一元的。
Comments | NOTHING