JAVA随堂笔记课【六】:数据类型,享元模式

数据类型


装箱(inbox)和拆箱(outbox)操作

在开始叨叨数据类型之前,先花一分钟时间讲明白一样东西:拆箱和装箱。

很简单,一句话的事儿:基本类型转换成类类型叫做装箱,类类型转换成基本类型叫做拆箱。

这里写图片描述

至于为什么开始先说这个,因为后面会有用。


基本数据类型和它们之间的强制转换

基本数据类型:int,float,double,char,byte。

当你这么写代码的时候,编译器永远会报错。试试看:

float f = 3.2;

是不是错的?当然是。为什么?
在Java中,小数类型默认double,整数则是int。刚才的3.2,类型实际上是double而不是float。

如果要对小数进行初始化,得在小数后加个f才行。

float f = 3.2f;

但是如果f是double类型呢?那就好办多了。不管你用下面哪种方法都OK。

double d = 3.2;
d = 3.2f;

这两行代码一点问题都没有。
想想也简单,先科普一下,float是4个字节,double是8个字节。
第一段代码里,float强制转化为double,用4个字节的东西去盛放8个字节的数据,当然瞬间爆炸。
而第二段代码里,4个字节的东西存放4个字节的数据,刚好。
第三段代码,8个字节的东西,不管是放8个字节的double还是4个字节的float,都放得下。

我们也可以由此得出结论:所谓强制类型转化,主要是高精度版本往低精度版本转换,需要手工进行。

数据类型的包装操作

先说一个简单的例子,你猜下结果是多少。

Integer i = new Integer(10);
System.out.println(i);

估计你也猜到结果会等于10了。是不是和大学课堂上讲的不太一样?当然。

Java已经对基本的类型进行了装箱。比较常用的有
Integer,Float,Double,Character,Byte。
(哦,当然一般最常用的还是String,后面会扯到。)

像Integer就是对int类型的数据进行了装箱。

当然Java类型还支持自动装箱和拆箱。


以整型(Integer)int为例:自动装箱和拆箱

(首先说一句,自动装箱是JDK1.5以后才支持的,JDK处于1.5以前的版本都不支持自动装箱和拆箱哦。)

简单点吧,两段代码就能告诉你我在说什么。

Integer i = new Integer(30); //手动装箱
Integer x = 30;        //自动装箱

int n = i.intValue();  //手动拆箱
int m = i;             //自动拆箱

这就是自动装箱拆箱和手动装箱拆箱。自己理解吧。

不过,好端端的int类型,干嘛要装箱?装箱以后有什么好处?那,下面就告诉你有什么好处。


装箱类型的好处

一个最容易举出来的例子就是,装箱过后的值终于可以设置为空(null)啦。在编写一些代码的时候值为空特别有帮助。比如:

Integer i = null;

我们还可以轻易找出该类型(比如,int)下的最大值和最小值。妈妈再也不用担心我要死记硬背啦好伐。

System.out.println(Integer.MAX_VALUE);
System.out.println(Integer.MIN_VALUE);

最后,我们还可以做一些之前不敢想的事情!
不得不说Java封装的有用的东西太多了,以至于以前需要沉思良久的东西,现在只需一行。比如:

//将字符串类型转换成装箱好的整型,并且+1
System.out.println(Integer.parseInt("123")+1);
//整数直接转换成二进制
System.out.println(Integer.toBinaryString(123));
//整数直接转换成八进制
System.out.println(Integer.toOctalString(123));
//同理十六进制的代码肯定也有就是我懒
//等等等等
想当年第一次用的时候,花了二十多分钟的时间搞了一个整数转二进制的代码,还觉得自己很吊。结果班里有个学渣跑过来看着我说了一句,你TM是不是傻,还自己写。。啊啊啊啊啊啊啊。

好了,数据类型到此结束,不叨叨了。next


享元模式


先说字符串,享元模式后面再讲

初入Java提及字符串,总有一些需要考虑的经典问题。下面给一个例子:

String str1 = new String("abcdefg");
String str2 = new String("abcdefg");

System.out.println(str1==str2);
好了,接下来你可以把这段代码粘贴在记事本上,然后找个写代码但是没学过Java的人来,之后你可以赌一顿饭,就猜结果是什么,而且先让他猜。接下来等着他请你吃饭就行了……嗯,对,没错,因为……

输出结果是……false。
str1和str2当然相等,但是为什么是false??
这就得提到Java有关指针的问题了。在学Java之前天天听学长们在那里说,Java大法好,退C++保平安……问他们为什么,理由千奇百怪什么理由都有,不过肯定少不了的一条就是,Java不需要指针。
Java真的没有指针么?


why?

首先,Java有指针。没有不需要指针的语言。只不过Java把他们隐藏在代码里,而且藏得非常好。
那么,指针在哪里?str1,str2,其实就可以看作是一个放在堆栈(stack)中的指针。

比如刚才说的那个例子(终于绕回来了)。还记得之前学过的Java变量在内存中的布局方式吗?

如果忘了可以回去简单看一下,赶快回来哦,想起怎么回事就行了。

我们分析一下,在print之前,线程中存放了两个数据,一个是String str1,另一个就是String str2。
然后,在堆中的数据是这样分布的:String str1指向了一个它自己new出来的abcdefg对象,String str2也指向了一个它自己new出来的abcdefg对象。但是问题在于,这两个abcdefg并不是一个对象,他们是分别独立的整体。

所以说,这时候输出这句话

System.out.println(str1 == str2);

它的真实作用其实是比较两个引用变量,是否指向同一个字符串对象。
由于不是一个对象,所以,当然就false啦。

我们在这种情况下想比较str1,str2的值怎么办呢?这么写就OK啦。

System.out.println(str1.equals(str2));

这样最后会返回true的。


好啦,开始说享元模式

还是要先看一段例子:

String s1 = "xyz";
String s2 = "xyz";
System.out.println(s1==s2);

现在这行代码如果运行,输出的是true还是false?
答案应该是true。
但!是!我不是说过,如果不是一个对象的话,输出的会是false吗?
没错,所以s1和s2指向的,就是同一个对象啊。

好了,到这里就要提及一下Java所说的享元模式了。什么是享元模式?

首先,我们来分三次解析一下每行的代码吧。

首先第一行

String s1 = "xyz";

这行代码没有任何问题,s1在线程的栈中,放了一行代码String s1。
然后,在堆中放置了一个对象,new(“xyz”)。注意这里用到了前面讲过的自动装箱。所以,只需要写s1 = “xyz”,Java就会自动把堆栈中的s1指到新建的对象去。

然后第二行,这一行是重点

String s2 = "xyz";

这行代码有什么问题?也没任何问题。
首先s2在线程的栈中,放了一行代码String s2;
然后,在堆中什么都没放!这次Java会把s2指到之前s1指向的xyz!理由很简单,因为已经存在了一个xyz,没有必要再新建一个了

最后第三行,询问s1和s2是否指向同一个对象?当然是了。


享元模式总结

java字符串一旦定义,将不能被修改,没有必要创建多个相同的字符串对象,完全可以复用。
为了提高效率,降低字符串对象的构建数量,java默认会复用字符串对象。
这就是享元模式经典的体现之一,Java。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值