Java基础
Int 和 Inetger
今天参见了一场电话面试其中被问到了Int 和Inetger 的区别,当时也就只谈:1.包装类型和原始数据类型,2.自动装箱和自动拆箱,也不知道知否全面。
之后还是需要将他们总结一下:
首先,int是我们常说的整形数字,是Java的8个原始数据类型(boolean、byte 、short、char、int、foat、double、long)之一。Java语言虽然号称一切都是对象,但原始数据类型是例外。
原始数据类型
那么原始数据类型又是什么呢?故事其实这样的在Java设计之初,它保留了一些和面向过程语言的特性(如:C),原始数据类型不是对象,没有方法,但是可以简单快速处理数据。
原始数据类型分类 :
- 整型:byte、short、int、long
- 浮点型:float、double
- 布尔型:boolean
- 字符:char
各种数据类型取值范围如下:
数据类型 | 字节 | 取值范围 |
byte | 1 | -2^-7 ~ 2^7-1(-128 ~ 127) |
short | 2 | -2^-15 ~ 2^15-1 |
int | 4 | -2^31 ~ 2^31-1 |
long | 8 | -2^63 ~ 2^63-1 |
float | 4 | 大约±3.402 823 47E+38F(6~7位有效数字) |
double | 8 | 大约±1.797 693 134 862 315 70E+308(15位有效数字) |
取值范围与字节数相关 1 b= 8 位,在记录时 有一个字节用来记录符号所以对于 byte来说他的取值范围位
-2^-7 ~ 2^7-1(-128 ~ 127)
其他基本型也是同样的道理。
其中
char类型:
表示单个字符,他的值需要用 ‘ ’括起来,如 ‘A’
boolean类型
它只有两个值 true 和 false;
包装类型
在Java 5中,引入了自动装箱和自动拆箱功能(boxing/unboxing),Java可以根据上下文,自动进行转换,极大地简化了相关编程。
关于Integer的值缓存,这涉及Java 5中另一个改进。构建Integer对象的传统方式是直接调用构造器,直接new一个对象。但是根据实践,我们发现大部分数据操作都是集中在有
限的、较小的数值范围,因而,在Java 5中新增了静态工厂方法valueOf,在调用它的时候会利用一个缓存机制,带来了明显的性能改进。按照Javadoc,这个值默认缓存是-128到127之间。
关于Integer中的缓存机制,废话不多先上代码
private static class IntegerCache {
static final int low = -128;
static final int high;
static final Integer cache[];
static {
// high value may be configured by property
int h = 127;
String integerCacheHighPropValue =
sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
if (integerCacheHighPropValue != null) {
try {
int i = parseInt(integerCacheHighPropValue);
i = Math.max(i, 127);
// Maximum array size is Integer.MAX_VALUE
h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
} catch( NumberFormatException nfe) {
// If the property cannot be parsed into an int, ignore it.
}
}
high = h;
cache = new Integer[(high - low) + 1];
int j = low;
for(int k = 0; k < cache.length; k++)
cache[k] = new Integer(j++);
// range [-128, 127] must be interned (JLS7 5.1.7)
assert IntegerCache.high >= 127;
}
private IntegerCache() {}
}
从代码中我们可以看出来它是来自Integer类中的一个静态内部类,有自己默认的无参构造函数。在static 块中将自己的属性cache 构造了一缓存数组,默认的范围是从 -128 到 127 我们也可以通过虚拟机的参数-XX:AutoBoxCacheMax来调整上限。
首先我们应该知道哪里用到了Cache ,我们才能分析出来如何很好的使用这个cache
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
到这里可能会有点奇怪辛辛苦苦构造的一个 cache 怎么就有了一个次 ?
其实当我们继续查看Inetger类所拥有的方法时,你会发现Inetger类他的主要功能有取最大值、最小值、位数、获取环境变量数值 、各种转换方法等;但是这些功能的前提到的各种静态工厂方法valueOf();
举个栗子:
//从系统的property文件中拿出一个integer
public static Integer getInteger(String nm, int val) {
Integer result = getInteger(nm, null);
return (result == null) ? Integer.valueOf(val) : result;
}
//返回一个指定进制 的数
public static Integer valueOf(String s, int radix) throws NumberFormatException {
return Integer.valueOf(parseInt(s,radix));
}
//将String字符串解码
public static Integer decode(String nm) throws NumberFormatException {
int radix = 10;
int index = 0;
boolean negative = false;
Integer result;
if (nm.length() == 0)
throw new NumberFormatException("Zero length string");
char firstChar = nm.charAt(0);
// Handle sign, if present
if (firstChar == '-') {
negative = true;
index++;
} else if (firstChar == '+')
index++;
// Handle radix specifier, if present
if (nm.startsWith("0x", index) || nm.startsWith("0X", index)) {
index += 2;
radix = 16;
}
else if (nm.startsWith("#", index)) {
index ++;
radix = 16;
}
else if (nm.startsWith("0", index) && nm.length() > 1 + index) {
index ++;
radix = 8;
}
if (nm.startsWith("-", index) || nm.startsWith("+", index))
throw new NumberFormatException("Sign character in wrong position");
try {
result = Integer.valueOf(nm.substring(index), radix);
result = negative ? Integer.valueOf(-result.intValue()) : result;
} catch (NumberFormatException e) {
// If number is Integer.MIN_VALUE, we'll end up here. The next line
// handles this case, and causes any genuine format error to be
// rethrown.
String constant = negative ? ("-" + nm.substring(index))
: nm.substring(index);
result = Integer.valueOf(constant, radix);
}
return result;
}
因此当遇到一些明确知道会涉及到较大数值的场景时,我们可以考虑尝试通过JVM 参数-XX:AutoBoxCacheMax来修改Integer 默认cache上限来优化我们的程序
Java中的异常处理机制
Exception 和 Error 都是继承了 Throwable 类,在 Java 中只有 Throwable 类型的实例才可以被抛出( throw )或者捕获( catch ),它是异常处理机制的基本组成类型。
Exception 和 Error 体现了 Java 平台设计者对不同异常情况的分类。 Exception 是程序正常运行中,可以预料的意外情况,可能并且应该被捕获,进行相应处理。
Error 是指在正常情况下,不大可能出现的情况,绝大部分的 Error 都会导致程序(比如 JVM 自身)处于非正常的、不可恢复状态。既然是非正常情况,所以不便于也不需要捕获,常
见的比如 OutOfMemoryError 之类,都是 Error 的子类。
Exception又分为 可检查 (checked)异常和 不检查 (unchecked)异常,可检查异常在源代码里必须显式地进行捕获处理,这是编译期检查的一部分。前面我介绍的不可查
的 Error ,是 Throwable 不是 Exception 。
不检查异常就是所谓的运行时异常,类似 NullPointerException 、 ArrayIndexOutOfBoundsException 之类,通常是可以编码避免的逻辑错误,具体根据需要来判断是否需要捕
获,并不会在编译期强制要求。
Throw early, catch late原则
throw 和throws 的区别
throw 是在方法内,表示抛出具体异常,则由该方法的使用者来处理异常。
Java 中只有throwabout的子类才可以被抛出 or 捕获
具体向外抛出的动作,所以它抛出的是一个异常实体类。若执行了Thow一定是抛出了某种异常
1.在捕获异常时需要尽量具体而不是 简单的 Catch Exception
2.只少使用logger 记录异常以方便后来的查找问题
Throws:
- 作用在方法的声明上,表示如果抛出异常,则由该方法的调用者来进行异常处理。
- 主要的声明这个方法会抛出会抛出某种类型的异常,让它的使用者知道捕获异常的类型。
- 出现异常是一种可能性,但不一定会发生异常。
讲讲MVC的思想
Spring中Bean的生命周期
创建和销毁两个过程
spring bean 的作用域:
Singleton,这是Spring的默认作用域,也就是为每个IOC容器创建唯一的一个Bean实例。
Prototype,针对每个getBean请求,容器都会单独创建一个Bean实例。
如果是 Web 容器,则支持另外三种作用域:
Request,为每个HTTP请求创建单独的Bean实例。
Session,很显然Bean实例的作用域是Session范围。
GlobalSession,用于Portlet容器,因为每个Portlet有单独的Session,GlobalSession提供一个全局性的HTTP Session。
AOP 动态代理
分布式ID
synchronized和ReentrantLock有什么区别呢?