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 之类,通常是可以编码避免的逻辑错误,具体根据需要来判断是否需要捕

获,并不会在编译期强制要求。

Java int的存储结构 java中 int_数据类型


Throw early, catch late原则

throw 和throws 的区别

throw 是在方法内,表示抛出具体异常,则由该方法的使用者来处理异常。
Java 中只有throwabout的子类才可以被抛出 or 捕获

具体向外抛出的动作,所以它抛出的是一个异常实体类。若执行了Thow一定是抛出了某种异常
1.在捕获异常时需要尽量具体而不是 简单的 Catch Exception
2.只少使用logger 记录异常以方便后来的查找问题

Throws:

  1. 作用在方法的声明上,表示如果抛出异常,则由该方法的调用者来进行异常处理。
  2. 主要的声明这个方法会抛出会抛出某种类型的异常,让它的使用者知道捕获异常的类型。
  3. 出现异常是一种可能性,但不一定会发生异常。

讲讲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有什么区别呢?