🦔
type
status
date
slug
summary
tags
category
icon
password
Property
BigInteger
在Java中,由CPU原生提供的整型最大范围是64位
long
型整数。使用long
型整数可以直接通过CPU指令进行计算,速度非常快。如果使用的整数范围超过了
long
型怎么办?这个时候,就只能用软件来模拟一个大整数。java.math.BigInteger
就是用来表示任意大小的整数。BigInteger
内部用一个int[]
数组来模拟一个非常大的整数:对
BigInteger
做运算的时候,只能使用实例方法,例如加法运算:和
long
型整数运算比,BigInteger
不会有范围限制,但缺点是速度比较慢。也可以把BigInteger
转换成long
型:🐻
type
status
date
slug
summary
tags
category
icon
password
Property
除了
int
等基本类型外,Java的其他类型全部都是class
(包括interface
),例如:String
Object
Runnable
Exception
- ...
class
(包括interface
)的本质是数据类型(Type
),无继承关系的数据类型无法赋值:而
class
是由JVM在执行过程中动态加载的。JVM在第一次读取到一种class
类型时,将其加载进内存。每加载一种
class
,JVM就为其创建一个Class
类型的实例,并关联起来。注:这里的Class
类型是一个名叫Class
的class
:🐻
type
status
date
slug
summary
tags
category
icon
password
Property
对任意的一个
Object
实例,只要获取了它的Class
,就可以获取它的一切信息。Class
类提供了以下几个方法来获取字段:- Field getField(name):根据字段名获取某个public的field(包括父类)
- Field getDeclaredField(name):根据字段名获取当前类的某个field(不包括父类)
- Field[] getFields():获取所有public的field(包括父类)
- Field[] getDeclaredFields():获取当前类的所有field(不包括父类)
一个
Field
对象包含了一个字段的所有信息:getName()
:返回字段名称,例如,"name"
;
🐻
type
status
date
slug
summary
tags
category
icon
password
Property
通过
Class
实例获取所有Field
对象,同样的,可以通过Class
实例获取所有Method
信息。Class
类提供了以下几个方法来获取Method
:Method getMethod(name, Class...)
:获取某个public
的Method
(包括父类)
Method getDeclaredMethod(name, Class...)
:获取当前类的某个Method
(不包括父类)
Method[] getMethods()
:获取所有public
的Method
(包括父类)
Method[] getDeclaredMethods()
:获取当前类的所有Method
(不包括父类)
一个
Method
对象包含一个方法的所有信息:getName()
:返回方法名称,例如:"getScore"
;
getReturnType()
:返回方法返回值类型,也是一个Class实例,例如:String.class
;
🐻
type
status
date
slug
summary
tags
category
icon
password
Property
通常使用
new
操作符创建新的实例:如果通过反射来创建新的实例,可以调用Class提供的newInstance()方法:
调用Class.newInstance()的局限是,它只能调用该类的public无参数构造方法。如果构造方法带有参数,或者不是public,就无法直接通过Class.newInstance()来调用。
为了调用任意的构造方法,Java的反射API提供了Constructor对象,它包含一个构造方法的所有信息,可以创建一个实例。Constructor对象和Method非常类似,不同之处仅在于它是一个构造方法,并且,调用结果总是返回实例:
通过Class实例获取Constructor的方法如下:
getConstructor(Class...)
:获取某个public
的Constructor
;
getDeclaredConstructor(Class...)
:获取某个Constructor
;
🐻
type
status
date
slug
summary
tags
category
icon
password
Property
比较Java的
class
和interface
的区别:- 可以实例化
class
(非abstract
)
- 不能实例化
interface
所有
interface
类型的变量总是通过某个实例向上转型并赋值给接口类型变量的:有没有可能不编写实现类,直接在运行期创建某个
interface
的实例呢?这是可能的,Java标准库提供了一种动态代理(Dynamic Proxy)的机制:可以在运行期动态创建某个
interface
的实例。什么叫运行期动态创建?所谓动态代理,是和静态相对应的。
静态代码定义接口:
🐻❄️
type
status
date
slug
summary
tags
category
icon
password
Property
什么是注解(Annotation)?注解是放在Java源码的类、方法、字段、参数前的一种特殊“注释”:
注释会被编译器直接忽略,注解则可以被编译器打包进入class文件,因此,注解是一种用作标注的“元数据”。
注解的作用
从JVM的角度看,注解本身对代码逻辑没有任何影响,如何使用注解完全由工具决定。
Java的注解可以分为三类:
- 第一类是由编译器使用的注解,例如:
- 第二类是由工具处理
.class
文件使用的注解,比如有些工具会在加载class的时候,对class做动态修改,实现一些特殊的功能。这类注解会被编译进入.class
文件,但加载结束后并不会存在于内存中。这类注解只被一些底层库使用,一般不必我们自己处理。
- 第三类是在程序运行期能够读取的注解,它们在加载后一直存在于JVM中,这也是最常用的注解。例如,一个配置了
@PostConstruct
的方法会在调用构造方法后自动被调用(这是Java代码读取该注解实现的功能,JVM并不会识别该注解)。
🐨
type
status
date
slug
summary
tags
category
icon
password
Property
我们先观察Java标准库提供的
ArrayList
,它可以看作“可变长度”的数组,因为用起来比数组更方便。实际上
ArrayList
内部就是一个Object[]
数组,配合存储一个当前分配的长度,就可以充当“可变数组”:如果用上述
ArrayList
存储String
类型,会有这么几个缺点:- 需要强制转型;
- 不方便,易出错。
例如,代码必须这么写:
很容易出现ClassCastException,因为容易“误转型”:
要解决上述问题,可以为
String
单独编写一种ArrayList
:🐨
type
status
date
slug
summary
tags
category
icon
password
Property
使用
ArrayList
时,如果不定义泛型类型时,泛型类型实际上就是Object
:此时,只能把
<T>
当作Object
使用,没有发挥泛型的优势。当我们定义泛型类型
<String>
后,List<T>
的泛型接口变为强类型List<String>
:当定义泛型类型
<Number>
后,List<T>
的泛型接口变为强类型List<Number>
:编译器如果能自动推断出泛型类型,就可以省略后面的泛型类型
编译器看到泛型类型
List<Number>
就可以自动推断出后面的ArrayList<T>
的泛型类型必须是ArrayList<Number>
,因此可以简写为: