Java基础教程——包装类
Java出道之时,自诩为“纯面向对象的语言”,意思是之前的所谓“面向对象语言”不纯。
但是,有人指责Java也不纯——8种基本类型并非类类型。为此,Java为他们提供可对应的类类型,是为“包装类”。
包装类
Java的八种基本数据类型用起来很方便,但不支持面向对象的编程机制,不属于Object继承体系,没有成员方法可调用。某些场合下,只能使用对象类型,不能使用基本类型,因此基本类型需要对应的包装类。
比如集合的定义:List<Integer> list;
写为List<int> list;就错了
Java提供了基本类型对应的包装类(Wrapper Class):
包装类一般就是把基本类型的首字母小写变为大写,但是int和char除外,它们的包装类要用全称。
下表中将int和char的写法加粗。
基本类型 | 包装类 |
---|---|
byte | Byte |
int | Integer |
short | Short |
long | Long |
float | Float |
double | Double |
boolean | Boolean |
char | Character |
另有一种说法,说Java中有9种基本类型,还要加一个void,其包装类是Void,但这种说法没有被普遍接受。
装箱和拆箱的概念
基本类型→(转为)→包装类,是为装箱
包装类→(转为)→基本类型,是为拆箱
JDK 1.5开始就提供了自动装箱、自动拆箱功能。借助该功能,开发者可以把基本类型当做对象使用,也可以把包装类的实例当做基本类型变量使用。
public class Test包装类 {
public static void main(String[] args) {
int a1 = 1000;// 定义基本类型
Integer objA = a1; // 自动装箱:Integer←int
int a2 = objA; // 自动拆箱:int←Integer
System.out.println(a2);
}
}
上述代码的解析:
int a1 = 1000; | |||
---|---|---|---|
自动装箱 | Integer objA =a1; | Integer←int | 本质上调用了Integer.valueOf(...) |
自动拆箱 | int a2 = objA; | int←Integer | 本质上调用了objA.intValue() |
包装类可以通过new实例化来构造
除Character类外,其它的包装类都有parseXxx方法:字符串→基本数据类型值
包装类有valueOf方法:字符串→包装类对象
示例代码(比较枯燥,瞅一眼就行):
public class Test构造包装类 {
public static void main(String[] args) {
构造包装类();
parseXxx_str_to_基本类型();
valueOf_str_to_Wrapper();
}
static void 构造包装类() {
System.out.println("---new 包装类---");
Boolean objBool = new Boolean(true);
Character objChar = new Character('X');
Byte objByte = new Byte((byte) 10);
Short objS = new Short((short) 50);
Integer objInt = new Integer(100);
Long objLong = new Long(1000);
Float objF = new Float(3.14);
Double objD = new Double(3.1415);
System.out.println(objBool);
System.out.println(objChar);
System.out.println(objByte);
System.out.println(objS);
System.out.println(objInt);
System.out.println(objLong);
System.out.println(objF);
System.out.println(objD);
}
static void parseXxx_str_to_基本类型() {
String str = "123";
System.out.println("---除Character类外,包装类都有parseXxx方法");
System.out.println("---parseXxx:字符串→基本数据类型值");
byte b = Byte.parseByte(str);
short s = Short.parseShort(str);
int i = Integer.parseInt(str);
long l = Long.parseLong(str);
float f = Float.parseFloat(str);
double d = Double.parseDouble(str);
boolean bl = Boolean.parseBoolean("TruE");
System.out.println(i);
System.out.println(s);
System.out.println(b);
System.out.println(l);
System.out.println(f);
System.out.println(d);
System.out.println(bl);
}
static void valueOf_str_to_Wrapper() {
String str = "123";
System.out.println("---valueOf方法:字符串→包装类对象");
Byte objByte = Byte.valueOf(str);
Short objShort = Short.valueOf(str);
Integer objInt = Integer.valueOf(str);
Long objLong = Long.valueOf(str);
Float objF = Float.valueOf(str);
Double objD = Double.valueOf(str);
Boolean objB = Boolean.valueOf("true");
Character obkChar = Character.valueOf('C');
System.out.println(objByte);
System.out.println(objShort);
System.out.println(objInt);
System.out.println(objLong);
System.out.println(objF);
System.out.println(objD);
System.out.println(obkChar);
System.out.println(objB);
}
}
Java中100等于100,1000不等于1000
public class Java1000 {
public static void main(String[] args) {
Integer a1 = 100;
Integer a2 = 100;
System.out.println(a1 + "==" + a2 + ":" + (a1 == a2));
a1 = 1000;
a2 = 1000;
System.out.println(a1 + "==" + a2 + ":" + (a1 == a2));
}
}
100100:true
10001000:false
原因:JDK源码的Integer类中,将-128~127做了缓存处理。
看看这段缓存:
package java.lang;
……
public final class Integer extends Number implements Comparable<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;
……
high = h;
……
// range [-128, 127] must be interned (JLS7 5.1.7)
assert IntegerCache.high >= 127;
}
private IntegerCache() {}
}
……
}
改改这段缓存:(看懂大概即可)
import java.lang.reflect.Field;
import java.util.Arrays;
public class TestInteger {
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
// 说明:IntegerCache是Integer中的一个内部类
// 源码:private static class IntegerCache{...}
// 1.取出Integer中定义的内部类(包括公共、私有、保护)
Class<?>[] classes = Integer.class.getDeclaredClasses();
System.out.println("Class数组:" + Arrays.toString(classes));
Class<?> classCache = classes[0];
System.out.println("IntegerCache:" + classCache);
// 2.取成员变量:cache
// 源码:static final Integer cache[];
Field fieldCache = classCache.getDeclaredField("cache");
System.out.println("Integer cache[]:" + fieldCache);
fieldCache.setAccessible(true);
// 3.取出cache的值
// field.get(obj):返回指定对象上由此Field表示的字段的值
Integer[] newCache = (Integer[]) fieldCache.get(classCache);
System.out.println("Integer[]:" + Arrays.toString(newCache));
// 0 : -128
// 1 : -127
// 2 : -126
// ...
// 127 : -1
// 128 : 0
// 129 : 1
// 130 : 2
// 131 : 3
// 132 : 4
// 133 : 5
newCache[132] = newCache[133];
int a = 2;
int b = a + a;
// public PrintStream printf(String format, Object ... args)
// 用的是Object类型,取包装类
System.out.println("println:" + a + "+" + a + "=" + b); // 2+2=4
System.out.printf("printf:%d + %d = %d\n", a, a, b); // 2+2=5
newCache[132] = 1999;
System.out.println("println:b = " + b);// println:正常的4
System.out.printf("printf:b = %d", b);// printf:新值1999
}
}
为什么System.out.printf的结果都是我们修改的值呢?可以推测,printf一定是到缓存中去取值了。
看看printf的源码:
public PrintStream printf(String format, Object ... args)
第二个参数是Object类型的(还是个可变参数),包装类是Object的子类,这里正是用的多态,用Object代表包装类的对象,取的正是Integer中的值,在-128~127范围内,取的正是缓存里的值。
最大值和最小值
通过包装类,我们可以取出数值类型的最大值和最小值,这些值在范围判断的时候很重要,但是非天才是记不住的,包装类可以帮我们快速找出来。
public class MAX_MIN {
public static void main(String[] args) {
System.out.println(Integer.MAX_VALUE);
System.out.println(Integer.MIN_VALUE);
System.out.println(Long.MAX_VALUE);
System.out.println(Long.MIN_VALUE);
System.out.println(Double.MAX_VALUE);
System.out.println(Double.MIN_VALUE);
}
}
2147483647
-2147483648
9223372036854775807
-9223372036854775808
1.7976931348623157E308
4.9E-324
*Java7增加的包装类功能:compare比较值的大小
public class TestIntegercompare {
public static void main(String[] args) {
Integer a1 = 100;
Integer a2 = 100;
System.out.println(a1 + "==" + a2 + ":" + (a1 == a2));// FALSE
a1 = 1000;
a2 = 1000;
System.out.println(a1 + "==" + a2 + ":" + (a1 == a2));// FALSE
// 包装类.compare方法:比较值的大小(大于:1/等于:0/小于:-1)
System.out.println(a1 + "==" + a2 + ":" + Integer.compare(a1, a2));
System.out.println("1 VS 2 : " + Integer.compare(1, 2));
System.out.println("2 VS 1 : " + Integer.compare(2, 1));
System.out.println("1 VS 1 : " + Integer.compare(1, 1));
}
}
*Java8增强的包装类,主要是支持无符号运算。
无符号数的最高位不再被当做符号位(不支持负数,最小值为0)
public class Java8Wapper {
public static void main(String[] args) {
byte b = -1;
int unsignedInt = Byte.toUnsignedInt(b);
System.out.println(unsignedInt);
long unsignedLong = Byte.toUnsignedLong(b);
System.out.println(unsignedLong);
}
}
255
255
Java基础教程——包装类的更多相关文章
- Java基础教程:面向对象编程[1]
Java基础教程:面向对象编程 内容大纲 Java语言概述 Java语言特点 1.Java为纯面向对象的语言,它能够直接反映现实生活中的对象.总之,Everything is object! 2.平台 ...
- Java基础教程(18)--继承
一.继承的概念 继承是面向对象中一个非常重要的概念,使用继承可以从逻辑和层次上更好地组织代码,大大提高代码的复用性.在Java中,继承可以使得子类具有父类的属性和方法或者重新定义.追加属性和方法. ...
- Java基础教程(12)--深入理解类
一.方法的返回值 当我们在程序中调用方法时,虚拟机将会跳转到对应的方法中去执行.当以下几种情况发生时,虚拟机将会回到调用方法的语句并继续向下执行: 执行完方法中所有的语句: 遇到return语句: ...
- Java基础教程:注解
Java基础教程:注解 本篇文章参考的相关资料链接: 维基百科:https://zh.wikipedia.org/wiki/Java%E6%B3%A8%E8%A7%A3 注解基础与高级应用:http: ...
- Java基础教程:网络编程
Java基础教程:网络编程 基础 Socket与ServerSocket Socket又称"套接字",网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个s ...
- Java基础教程(5)--变量
一.变量 1.变量的定义 正如上一篇教程<Java基础教程(4)--面向对象概念>中介绍的那样,对象将它的状态存在域中.但是你可能仍然有一些疑问,例如:命名一个域的规则和惯例是什么?除 ...
- Java基础教程:Lambda表达式
Java基础教程:Lambda表达式 本文部分内容引用自OneAPM:http://blog.oneapm.com/apm-tech/226.html 引入Lambda Java 是一流的面向对象语言 ...
- Java基础教程:泛型基础
Java基础教程:泛型基础 引入泛型 传统编写的限制: 在Java中一般的类和方法,只能使用具体的类型,要么是基本数据类型,要么是自定义类型.如果要编写可以应用于多种类型的代码,这种刻板的限制就会束缚 ...
- Java基础教程:多线程基础(1)——基础操作
Java:多线程基础(1) 实现多线程的两种方式 1.继承Thread类 public class myThread extends Thread { /** * 继承Thread类,重写RUN方法. ...
随机推荐
- 打造跨平台.NET Core后台服务
续之前讲的在TopShelf上部署ASP.NET Core程序,作为后台服务运行,自从.NET Core 3.0出现以后,出现了自带的Generic Host,使得自托管服务变为可能.这种方式和Top ...
- 设计模式:策略模式(根据参数,调用不同的service接口)
1.定义类容器providers,当spring加载时@PostConstruct(类似构造方法),会先执行init() : 在init()中,反射"cn.jdk18"的所有带自定 ...
- 【转】Key Presses
FROM:http://lazyfoo.net/tutorials/SDL/04_key_presses/index.php Key Presses Last Updated 6/11/19 Xing ...
- 探索G1垃圾回收器
前言 最近王子因为个人原因有些忙碌,导致文章更新比较慢,希望大家理解,之后也会持续和小伙伴们一起共同分享技术干货. 上篇JVM的文章中我们对ParNew和CMS垃圾回收器已经有了一个比较透彻的认识,感 ...
- [Luogu P2341] [HAOI2006]受欢迎的牛 (缩点+bitset)
题面 传送门:https://www.luogu.org/problemnew/show/P2341 Solution 前排提示,本蒟蒻做法既奇葩又麻烦 我们先可以把题目转换一下. 可以把一头牛喜欢另 ...
- Ubuntu17.10 React Native 环境搭建
React Native 环境搭建 环境:ubuntu17.10 安装依赖 必须安装的依赖有:Node.React Native 命令行工具以及 JDK 和 Andriod Studio. 安装nod ...
- 80386学习(一) 80386CPU介绍
一.80386CPU介绍 Inter80386CPU是Inter公司于1985年推出的第一款32位80x86系列的微处理器.80386的数据总线是32位的,其地址总线也是32位,因而最大可寻址4GB的 ...
- <摘自>飞:jxl简析2 [ http://www.emlog.net/fei ]
[<摘自>飞:jxl简析:http://www.emlog.net/fei] (二)应用 在进行实践前 , 我们需要对 excel 有一个大致的了解 ,excel 文件由一个工作簿 (Wo ...
- 弹性盒模型flex-grow的计算
flex-grow属性是弹性盒布局模块的子属性. 它定义了弹性项目在必要时增长的能力. 它接受作为比例的无单位值. 它决定了项目应在伸缩容器内部占用多少可用空间. 例如,如果所有项目的flex-gro ...
- waitpid()系统调用学习
waitpid()的头文件 #include <sys/types.h> #include <sys/wait.h> pid_t waitpid(pid_t pid,int ...