大橙子网站建设,新征程启航
为企业提供网站建设、域名注册、服务器等服务
◆什么是自动包装?
我们提供的服务有:成都做网站、网站制作、微信公众号开发、网站优化、网站认证、甘孜州ssl等。为超过千家企事业单位解决了网站和推广的问题。提供周到的售前咨询和贴心的售后服务,是有科学管理、有技术的甘孜州网站制作公司
自动包装,又称自动封装,即把基础数据类型(如 int)转换成基础类型封装类的对象(如 new Integer() )
拆箱就是装箱的反过程,即把基础类型封装类的对象(如 new Integer())转换为基础数据类型(如 int)。
装箱: Integer a = new Integer() ;
a = 100 ; //1.5以前不支持为对象如此赋值
拆箱: int b = new Integer(100) ;
◆为什么要自动封装?
1、因为封装的数据类型就是一个对象,可以拥有属性和方法,有了这些属性和方法,我们就可以用它们来处理数据.比如Integer对象里的parseInt(String s),可以把字符串转换成int类型等
2、java是面向对象的一门语言,到处都是对象,有些时候我们需要传递的值必须是对象类型的.比如:structs框架里的DynaActionForm,当JSP页面数据传到dform中时,我们需要(Integer)dform.get("qty");,而(int)dform.get("qty");这样是错误的.
◆8种基本数据类型及其封装类
.type .Class
boolean Boolean
byte Byte
char Character
double Double
float Float
int Integer
long Long
short Short
封装在java中有两种表现
1.用类封装一个事物的属性和方法。
2.用方法来封装一个固定的算法。
楼上所说的其实是封装的程度不一样,在面向对象的术语中粒度来表示这个程度。
封装其实是要看情况而定的,如果你这个类是描述人的,需要这个人完成一些基本的动作,如吃饭,走路,那么就不用把细胞也封装进来。但是如果“人”这个类,需要做医学的研究用,那么就需要封装细胞这个属性了。
代码打多了就自然能理解了,不是一个复杂的概念。呵呵。
3 Autoboxing and Unboxing 自动装箱与解箱
3.1 Converting Primitives to Wrapper Types
看一下代码
int foo = 0;
Integer integer = foo;
反编译class文件看到
int foo = 0;
Integer integer = Integer.valueOf(foo);
是编译器帮助做了类型转换,各原始类型分别与它wrapper之间对应
Number n = 0.0f;
上面的申明显示从float转到Float,再从Float转到Number
3.2 Converting Wrapper Types to Primitives
看一下代码
Integer integer = 1;
int i = integer;
反编译class文件看到
Integer integer = Integer.valueOf(1);
int i = integer.intValue();
先装箱再解箱,从上代码可以看出,如果
Integer integer = null;
int i = integer.intValue();
那么这个代码必定报NullPointerException,所以在解箱的时候需特别注意这点
3.3 Incrementing and Decrementing Wrapper Types
看一下代码
Integer counter = 1;
while (counter10) {
System.out.printf("Iteration %d%n", counter++);
}
反编译class文件看到
Object aobj[];
for(Integer counter = Integer.valueOf(1); counter.intValue() 10; System.out.printf("Iteration %d%n", aobj))
{
aobj = new Object[1];
counter = Integer.valueOf(counter.intValue() + 1);
aobj[0] = counter;
}
在这里我们看到自增长运算符++在这里也是可以使用的,编译后实际上在在int上操作,然后再赋给counter
3.4 Boolean Versus boolean
看一下代码A
Boolean case1 = true;
Boolean case2 = true;
boolean case3 = false;
Boolean result = (case1 || case2) case3;
反编译class文件看到
Boolean case1 = Boolean.valueOf(true);
Boolean case2 = Boolean.valueOf(true);
boolean case3 = false;
Boolean result = Boolean.valueOf((case1.booleanValue() || case2.booleanValue()) case3);
在进行或运算和与运算的时候都用到了unboxing,然后再把结果autoboxing
For inquiring minds, primitives are boxed up to wrapper types in equality comparisons. For operators such as , =, and so forth, the wrapper types are unboxed to primitive types.
看一下代码B
Integer i1 = 256;
Integer i2 = 256;
if (i1 == i2) {
System.out.println("Equal!");
} else {
System.out.println("Not equal!");
}
在大多数的jvm里返回的是not equal,==运算符直接是对两个object intances的比较,不多内存地址,结果当然是not equal,当然也有少部分最优化的jvm可能会返回equal,如果优化的策略是创建一个instance实例
看一下代码C
Integer i1 = 100;
Integer i2 = 100;
if (i1 == i2) {
System.out.println("Equal!");
} else {
System.out.println("Not equal!");
}
返回结果是equal,记住int值在-127到127的范围里,这样的两个同int值的Integer对象jvm是只分配一个内存地址的
3.5 Conditionals and Unboxing
看一下代码A
Boolean arriving = false;
Boolean late = true;
System.out.println(arriving ? (late ? "It's about time!" : "Hello!") :
(late ? "Better hurry!" : "Goodbye"));
反编译看
Boolean arriving = Boolean.valueOf(false);
Boolean late = Boolean.valueOf(true);
System.out.println(arriving.booleanValue() ? late.booleanValue() ? "It's about time!" : "Hello!" : late.booleanValue() ? "Better hurry!" : "Goodbye");
输出是Better hurry!
看一下代码B
String s = "hello";
StringBuffer sb = new StringBuffer("world");
boolean mutable = true;
CharSequence cs = mutable ? sb : s;
反编译看到
String s = "hello";
StringBuffer sb = new StringBuffer("world");
boolean mutable = true;
CharSequence cs = ((CharSequence) (mutable ? ((CharSequence) (sb)) : ((CharSequence) (s))));
现在的jdk中String和StringBuffer都实现了CharSequence,故String和StringBuffer都转成CharSequence
3.6 Method Overload Resolution
看一下代码
public static void main(String[] args) {
int foo = 1;
doSomething(foo);
}
public static void doSomething(double num) {
System.out.println("double called");
}
public static void doSomething(Integer num) {
System.out.println("Integer called");
}
猜一下哪个被调用呢?
输入的结果是"double called",在这里,你是不是会想到autoboxing?实际上在新的java中方法的调用遵循以下3个规则
1:不考虑boxing,unboxing及变参,而是先遵循1.4下的调用顺序
2:1.4下的规则找不到,参数boxing或者unboxing,找可调用的方法
3:以上规则找不到,考虑变参的方式调用方法
可以。
一个代码可以封装多个resquest进行调用,只是在调用的过程中必须保证方法名称和调用的方式一致。
封装的概念来自对面向对象的编程模式 比如说一个方法,你把他放到一个类里面, 下次如果别的地方要用到的话,直接调用这个方法就行了,不用再重新编写。
说给人家听,我们就说的通俗简单点: 代码封装的好处:第一点在于安全,JAVA中类的一个属性,我们一般会在类中将其私有化然后getter和setter方法对外提供得到和设置的方法,这就好比自动存提款机,钱就是我们要的属性,要的数据,放在那直接去拿可以吗?很明显不行,所以自动存提款机提供了取钱的方法和存钱方法,而你不用知道钱从哪来要到哪里去。第二点在于方便:方法也是封装的一种体现,有一个功能我们要反复调用,每次写同样的代码吗?答案很明显,不要!,我们写个方法,把这段功能代码封装成一个方法,需要的时候调用方法名就可以了,不是吗? 关于package:如果一个项目很大的话,会分成很多小组,每个小组会有很多开发人员,大家在编写代码时说不定会出现同样的类名,问题就来了,我在调类的时候,调的是哪个?所以每个小组用不同的包名,这样来区分类所在的位置。好,如果你说项目编码之前详细设计说的很清楚了,类不可能出现同名,那么包的另外一个好处在于相似用途的类放在一个包下可以方便管理和查找,比如java.util包,如查没有包的存在,我想查API看有哪些集合框架,你说方便不 权限修饰符的作用就是:你很有钱,你愿意告诉谁你很有钱需要的时候可以来找你,你的亲属?你的儿子?还是全世界的所有人?你自己有必要告诉谁 那么他们缺钱的时候就会想到你
java编程思想中其实就提到了,还是做了一下总结:
1.基本类型只能按值传递,而每个基本类型对应的封装类是按引用传递的。
2.从性能上说java中的基本类型是在堆栈上创建的,而所有的对象类型都是在堆上创建的,(对象的引用在堆栈上创建)。比如
Integer i=new Integer(10); 其中new Integer()是在堆上创建的,而他的引用Integer i是在堆栈上。 封装类的出现,是为了更方便的使用一些基本类型不具备的方法,比如valueOf(),toString()等等。还有你如果想传递一个int对象的引用,而不是值,那只能用封装类。
在堆栈上分配内存的调用效率和在堆上分配内存的效率差太多了。虽然在堆栈上分配内存效率高,不过在堆栈上分配内存有内存泄露的问题。(这是一个平庸程序员基本解决不了的问题...)java用了一种很天才的方法提高了在堆上分配内存的效率,尽管如此,java还是慢。他不太可能达到向c++那么快,尽管他一直在承诺总有一天虚拟机会和机器码速度一样快。
JDK5.0开始可以自动封包了 ,也就是基本数据可以自动封装成封装类,基本数据类型的好处就是速度快(不涉及到对象的构造和回收),封装类的目的主要是更好的处理数据之间的转换,方法很多,用起来也方便。
当然,封装类型的传递是引用传递,比如
Integer a = new Integer(1);
表示一个Integer类型的引用a引用了一块内存,这块内存中的数据是1; 而a中所存的则是这块内存的引用(地址),把a传给别的方法或对象时,则是把a的引用传递过去了。
类型之间的转换:
String b = "123456";
int c = Integer.parseInt(b);
表示把字符串123456转成整型数字,其中parseInt是静态方法,可以直接使用
还有一点,在某些场合,需要用到封装类,比如一个集合List,它只能往里面添加对象,也就是Object,那么直接存数字肯定是不行 的,则需要将数字封装成封装类型对象再存到该List中,如
List list = new ArrayList();
list.add(new Integer(1));
list.add(new Integer(2));
list.add(new Integer(3));
list.add(new Integer(4));
JDK5.0以后可以自动封包,所以可以简写成
List list = new ArrayList();
list.add(1);
list.add(2);
list.add(3);
list.add(4);