作为一名程序员,我觉得会多门语言的前提,必须把一门语言熟练掌握,才能触类旁通,因此,也就出现了这次的Java基础与深入之旅啦!欢迎大家关注这一系列。
这一系列打算慢慢地去接触源码,并且列出相关的题目,对于完全的初学者的话,我到时候会搜一套我认为比较好的培训机构的视频以及给些社区资料和相关博客咯。让我们一起开始思考,深入学习Java吧。
这篇文章就数据类型咯-文章结构:1. 基本数据类型的系统描述;2.数据类型的包装类理解(含源码解析);3.数据类型转换、装包拆包等一些小坑。
一、基本数据类型的系统描述:
1. 总述:Java基本数据类型分为两大类:boolean类型和数值类型。数值类型可分为整数类型和浮点类型,而其中字符类型可单独对待。所以Java只包含8种基本数据类型。
!注意!字符串不是基本数据类型,字符串是一个类,是一个引用类型。这个在下一篇我们会仔细讨论它!
boolean 数值只有true和false,不能用0代替。其他数值类型不能转换成boolean。包装类–Boolean
byte 内存8位,无符号位时最大存储255,表数范围:-128~127。包装类–Byte
short 内存16位,无符号位时最大存储65536,表数范围:-32768~32767。包装类–Short
int 内存32位,无符号位时最大存储2的32次方减1,表数范围:负的2的31次方到正的2的31次方减1。包装类–Integer。
long 内存64位,无符号位时最大存储2的64次方减1,表数范围:负的2的63次方到正的2的63次方减1。包装类–Long。
float 内存32位,数据范围在3.4e-45~1.4e38,直接赋值时必须在数字后加上f或F。包装类–Float。
double 内存64位,数据范围在4.9e-324~1.8e308,赋值时可以加d或D也可以不加。包装类–Double。
char:16位,存储Unicode字符集,用单引号赋值。可以参与加减乘除运算的,也可以比较大小的!!包装类–Character。
二、数据类型的包装类理解(含部分源码解析)
首先要知道为什么Java会为每一个基础数据类型都提供一个相应包装类的目的,在于将Java的所有东西都抽象成对象,可以更方便的控制和使用。这就是面向对象!
然后对于包装类,主要作用是:1.作为和基本数据类型对应的类类型存在,方便涉及到对象的操作。2.包含每种基本数据类型的相关属性如最大值、最小值等,以及相关的操作方法。
下面我们将一起讨论下包装类中的重要源码!!
1.深入boolean基本类型、Boolean类以及细节点:
public final class Boolean implements java.io.Serializable,
Comparable<Boolean>{
public static final Boolean TRUE = new Boolean(true);
public static final Boolean FALSE = new Boolean(false);
private final boolean value;
public Boolean(boolean value) {
this.value = value;
}
public Boolean(String s) {
this(parseBoolean(s));
}
public static boolean parseBoolean(String s) {
return ((s != null) && s.equalsIgnoreCase("true"));
}
public static Boolean valueOf(String s) {
return parseBoolean(s) ? TRUE : FALSE;
}
public static int hashCode(boolean value) {
return value ? 1231 : 1237;
}
}
总括下:1.boolean是基础数据类型,而Boolean是一个类。2.boolean一般存在于桟空间中,而Boolean对象存在堆空间中。3.boolean有true和false俩种值,Boolean除了true和false外,还有null。
下面我们看份代码:(解析在代码中)
public class Main {
public static void main (String []args)
{
Boolean bool1 = Boolean.valueOf(true);
Boolean bool2 = Boolean.valueOf("True");
Boolean bool3 = Boolean.valueOf("ASD");
boolean x1 = bool1.booleanValue();
boolean x2 = bool2.booleanValue();
System.out.println("bool1:" + x1 + ",bool2:" + x2 + ",bool3:" + bool3);
boolean x3 = bool1.equals(bool2);
boolean x4 = bool1.equals(bool3);
System.out.println("bool1.equals(bool2):" + x3 + ",bool1.equals(bool3):" + x4);
String str1 = Boolean.toString(bool1);
String str2 = Boolean.toString(false);
String str3 = bool3.toString();
System.out.println("bool1:" + str1 + ",str2:" + str2 + ",bool3:" + str3);
boolean x5 = Boolean.parseBoolean("ASD");
System.out.println(x5);
}
}
2.深入byte基本类型
先来份Byte源码
public final class Byte extends Number implements Comparable<Byte>{
public static final int SIZE = 8;
public Byte(byte value) {
this.value = value;
}
public Byte(String s) throws NumberFormatException {
this.value = parseByte(s, 10);
}
private static class ByteCache {
private ByteCache(){}
static final Byte cache[] = new Byte[-(-128) + 127 + 1];
static {
for(int i = 0; i < cache.length; i++)
cache[i] = new Byte((byte)(i - 128));
}
}
public static byte parseByte(String s, int radix)
throws NumberFormatException {
int i = Integer.parseInt(s, radix);
if (i < MIN_VALUE || i > MAX_VALUE)
throw new NumberFormatException(
"Value out of range. Value:\"" + s + "\" Radix:" + radix);
return (byte)i;
}
public static Byte decode(String nm) throws NumberFormatException {
int i = Integer.decode(nm);
if (i < MIN_VALUE || i > MAX_VALUE)
throw new NumberFormatException(
"Value " + i + " out of range from input " + nm);
return valueOf((byte)i);
}
}
解释radix的作用
b[0] = Byte.parseByte(“11”, 2) = 3
表示 字符串11以2为基数表示为10进制的byte值是 3 ,这里的11表示的是一个2进制数
b[0] = Byte.parseByte(“11”, 3) = 4
表示 字符串11以3为基数表示为10进制的byte值是 4 ,这里的11表示的是一个3进制数
byte=55;
3.就是重点的int与Integer啦
先吃份源码Integer解析套餐
public final class Integer extends Number implements Comparable<Integer> {
public static final Class<Integer> TYPE = (Class<Integer>) Class.getPrimitiveClass("int");
final static char[] digits = {
'0' , '1' , '2' , '3' , '4' , '5' ,
'6' , '7' , '8' , '9' , 'a' , 'b' ,
'c' , 'd' , 'e' , 'f' , 'g' , 'h' ,
'i' , 'j' , 'k' , 'l' , 'm' , 'n' ,
'o' , 'p' , 'q' , 'r' , 's' , 't' ,
'u' , 'v' , 'w' , 'x' , 'y' , 'z'
};
public Integer(int value) {
this.value = value;
}
public Integer(String s) throws NumberFormatException {
this.value = parseInt(s, 10);
}
public static String toString(int i, int radix) {
if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX)
radix = 10;
if (radix == 10) {
return toString(i);
}
char buf[] = new char[33];
boolean negative = (i < 0);
int charPos = 32;
if (!negative) {
i = -i;
}
while (i <= -radix) {
buf[charPos--] = digits[-(i % radix)];
i = i / radix;
}
buf[charPos] = digits[-i];
if (negative) {
buf[--charPos] = '-';
}
return new String(buf, charPos, (33 - charPos));
}
public static String toString(int i) {
if (i == Integer.MIN_VALUE)
return "-2147483648";
int size = (i < 0) ? stringSize(-i) + 1 : stringSize(i);
char[] buf = new char[size];
getChars(i, size, buf);
return new String(buf, true);
}
static void getChars(int i, int index, char[] buf) {
int q, r;
int charPos = index;
char sign = 0;
if (i < 0) {
sign = '-';
i = -i;
}
while (i >= 65536) {
q = i / 100;
r = i - ((q << 6) + (q << 5) + (q << 2));
i = q;
buf [--charPos] = DigitOnes[r];
buf [--charPos] = DigitTens[r];
}
for (;;) {
q = (i * 52429) >>> (16+3);
r = i - ((q << 3) + (q << 1));
buf [--charPos] = digits [r];
i = q;
if (i == 0) break;
}
if (sign != 0) {
buf [--charPos] = sign;
}
}
final static int [] sizeTable = { 9, 99, 999, 9999, 99999, 999999, 9999999,
99999999, 999999999, Integer.MAX_VALUE };
static int stringSize(int x) {
for (int i=0; ; i++)
if (x <= sizeTable[i])
return i+1;
}
public static int parseInt(String s, int radix)
throws NumberFormatException
{
if (s == null) {
throw new NumberFormatException("null");
}
if (radix < Character.MIN_RADIX) {
throw new NumberFormatException("radix " + radix +
" less than Character.MIN_RADIX");
}
if (radix > Character.MAX_RADIX) {
throw new NumberFormatException("radix " + radix +
" greater than Character.MAX_RADIX");
}
int result = 0;
boolean negative = false;
int i = 0, len = s.length();
int limit = -Integer.MAX_VALUE;
int multmin;
int digit;
if (len > 0) {
char firstChar = s.charAt(0);
if (firstChar < '0') {
if (firstChar == '-') {
negative = true;
limit = Integer.MIN_VALUE;
} else if (firstChar != '+')
throw NumberFormatException.forInputString(s);
if (len == 1)
throw NumberFormatException.forInputString(s);
i++;
}
multmin = limit / radix;
while (i < len) {
digit = Character.digit(s.charAt(i++),radix);
if (digit < 0) {
throw NumberFormatException.forInputString(s);
}
if (result < multmin) {
throw NumberFormatException.forInputString(s);
}
result *= radix;
if (result < limit + digit) {
throw NumberFormatException.forInputString(s);
}
result -= digit;
}
} else {
throw NumberFormatException.forInputString(s);
}
return negative ? result : -result;
}
public static int parseInt(String s) throws NumberFormatException {
return parseInt(s,10);
}
private static class IntegerCache {
static final int low = -128;
static final int high;
static final Integer cache[];
static {
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);
h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
} catch( NumberFormatException nfe) {
}
}
high = h;
cache = new Integer[(high - low) + 1];
int j = low;
for(int k = 0; k < cache.length; k++)
cache[k] = new Integer(j++);
assert IntegerCache.high >= 127;
}
private IntegerCache() {}
}
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
}
使用Integer事例代码:
public static void main (String []args) {
Integer i =null;
i = Integer.valueOf(10);
System.out.println(">>>>"+i.toString());
}
public static void main(String[] args) {
Integer a1 = 1
Integer a2 = 1
Integer b1 = 200
Integer b2 = 200
Integer c1 = Integer.valueOf(1)
// Integer c2 = new Integer(1)
Integer c2 = Integer.valueOf(1)
Integer d1 = Integer.valueOf(200)
Integer d2 = Integer.valueOf(200)
System.out.println("a1==a2?" + (a1 == a2))
System.out.println("b1==b2?" + (b1 == b2))
System.out.println("c1==c2?" + (c1 == c2))
System.out.println("d1==d2?" + (d1 == d2))
}
上面一段代码的运行结果就是我们要深思的东西啦,也是结合源码要懂的东西。
a1==a2? true
b1==b2? false
c1==c2? false
d1==d2? false
第一个为什么是true呢,因为Integer的缓存机制嘛,刚刚我们看到的,缓存了[-128,127],这些可以直接取出。而剩余的为什么是false,因为他们都超过了缓存的那个范围,就建了个新对象咯。
至于short、float、double这类的包装类设计原理有的跟Integer差不多,但是比如Double,很难去阅读,感觉自己程度还不够,以后会补上。而Character这个包装类,,源码8000多行,我们就讨论它的一些基本知识吧。
4.Character的基本了解:
Character 类在对象中包装一个基本类型 char 的值。Character 类型的对象包含类型为 char 的单个字段。该类提供了几种方法,以确定字符的类别(小写字母,数字,等等),并将字符从大写转换成小写,从小写转换成大写。Character 类的方法和数据是通过 UnicodeData 文件中的信息定义的。至于Unicode 大家就百度了解下就好。
5.还有一份挺重要的源码,就是Long类:
public final class Long extends Number implements Comparable<Long> {
@Native public static final long MIN_VALUE = 0x8000000000000000L;
@Native public static final long MAX_VALUE = 0x7fffffffffffffffL;
public static final Class<Long> TYPE = (Class<Long>) Class.getPrimitiveClass("long");
public static String toUnsignedString(long i, int radix) {
if (i >= 0)
return toString(i, radix);
else {
switch (radix) {
case 2:
return toBinaryString(i);
case 4:
return toUnsignedString0(i, 2);
case 8:
return toOctalString(i);
case 10:
long quot = (i >>> 1) / 5;、
long rem = i - quot * 10;
return toString(quot) + rem;
case 16:
return toHexString(i);
case 32:
return toUnsignedString0(i, 5);
default:
return toUnsignedBigInteger(i).toString(radix);
}
}
}
private static BigInteger toUnsignedBigInteger(long i) {
if (i >= 0L)
return BigInteger.valueOf(i);
else {
int upper = (int) (i >>> 32);
int lower = (int) i;
return (BigInteger.valueOf(Integer.toUnsignedLong(upper))).shiftLeft(32).
add(BigInteger.valueOf(Integer.toUnsignedLong(lower)));
}
}
public static String toHexString(long i) {
return toUnsignedString(i, 4);
}
public static String toOctalString(long i) {
return toUnsignedString(i, 3);
}
public static String toBinaryString(long i) {
return toUnsignedString(i, 1);
static int stringSize(long x) {
long p = 10;
for (int i=1; i<19; i++) {
if (x < p)
return i;
p = 10*p;
}
return 19;
}
public static long parseLong(String s, int radix)
throws NumberFormatException
{
if (s == null) {
throw new NumberFormatException("null");
}
if (radix < Character.MIN_RADIX) {
throw new NumberFormatException("radix " + radix +
" less than Character.MIN_RADIX");
}
if (radix > Character.MAX_RADIX) {
throw new NumberFormatException("radix " + radix +
" greater than Character.MAX_RADIX");
}
long result = 0;
boolean negative = false;
int i = 0, len = s.length();
long limit = -Long.MAX_VALUE;
long multmin;
int digit;
if (len > 0) {
char firstChar = s.charAt(0);
if (firstChar < '0') {
if (firstChar == '-') {
negative = true;
limit = Long.MIN_VALUE;
} else if (firstChar != '+')
throw NumberFormatException.forInputString(s);
if (len == 1)
throw NumberFormatException.forInputString(s);
i++;
}
multmin = limit / radix;
while (i < len) {
digit = Character.digit(s.charAt(i++),radix);
if (digit < 0) {
throw NumberFormatException.forInputString(s);
}
if (result < multmin) {
throw NumberFormatException.forInputString(s);
}
result *= radix;
if (result < limit + digit) {
throw NumberFormatException.forInputString(s);
}
result -= digit;
}
} else {
throw NumberFormatException.forInputString(s);
}
return negative ? result : -result;
}
public static long parseLong(String s) throws NumberFormatException {
return parseLong(s, 10);
}
public static Long valueOf(String s, int radix) throws NumberFormatException {
return Long.valueOf(parseLong(s, radix));
}
public static Long valueOf(String s) throws NumberFormatException
{
return Long.valueOf(parseLong(s, 10));
}
private static class LongCache {
private LongCache(){}
static final Long cache[] = new Long[-(-128) + 127 + 1];
static {
for(int i = 0; i < cache.length; i++)
cache[i] = new Long(i - 128);
}
}
public static Long valueOf(long l) {
final int offset = 128;
if (l >= -128 && l <= 127) {
return LongCache.cache[(int)l + offset];
}
return new Long(l);
}
public int hashCode() {
return (int)(value ^ (value >>> 32));
}
public boolean equals(Object obj) {
if (obj instanceof Long) {
return value == ((Long)obj).longValue();
}
return false;
}
}
6.列出一下包装类的共性:
(1)带有基本值参数并创建包装类对象的构造函数.如可以利用Integer包装类创建对象,Integer obj=new Integer(145)
Integer obj=new Integer(145);
(2)带有字符串参数并创建包装类对象的构造函数.如new Integer(“-45.36”);
(3)可生成对象基本值的typeValue方法,如obj.intValue();
int num=obj.intValue();
(4)将字符串转换为基本值的 parseType方法,如Integer.parseInt(args[0]);
(5)因为有装进Map的几率,所以java设计了包装类里的哈希值,生成哈稀表代码的hashCode方法,如obj.hasCode();
(6)对同一个类的两个对象进行比较的equals()方法,如obj1.eauqls(obj2);
(7)生成字符串表示法的toString()方法,如obj.toString().
(8)自动装包/拆包大大方便了基本类型数据和它们包装类地使用。
自动装包:基本类型自动转为包装类。例如(int >> Integer)
自动拆包:包装类自动转为基本类型。例如(Integer >> int)
三、数据类型转换、装包拆包等一些小坑。
(1).类型转换:
基础:1.自动类型转换-系统支持把某种基本类型的值直接赋给另一种基本类型的变量。
规则:如下图,从左到右自动转换。
2.强制类型转换-视图把表数范围大的类型转换为表数范围小的类型时,容器引起信息丢失。另:字符串不能直接转换为基本类型,但可通过基本类型对应的包装类实现转换成基本类型。如以下代码:
String a = "45";
int value=Integer.parseInt(a);
3.自动提升规则:当一个算术表达式中包含多个基本类型的值时,所有的byte类、short和char类型会被提示到int类型
(2)自动装包与拆包:自动装包/拆包大大方便了基本类型数据和它们包装类地使用。
自动装包:基本类型自动转为包装类.(int >> Integer)
自动拆包:包装类自动转为基本类型.(Integer >> int)
使用装包后,我们就可以用集合去存放基本类型啦。比如:Integer先自动转换为int进行加法运算,然后int再次转换为Integer。
int a = 3;
Collection c = new ArrayList();
c.add(a);//自动转换成Integer.自动装包
Integer b = new Integer(2);
c.add(b + 2);
好了,深入Java基础(一)——基本数据类型及其包装类讲完了。本博客是经过仔细其他类型的博客,结合源代码注释,并在这里做出进一步拓展以及写出自己的理解。另外,这个系列会逐步更新,也希望阅读更多源码,分享经验给大家。欢迎在下面指出错误,共同学习!!你的点赞是对我最好的支持!!
这个系列的文章因为涉及很多源码,所以会根据网友们的反应以及我的学习深入去补充。希望大家一起来讨论学习。
转载请注明:【JackFrost的博客】