java接口可以创建对象吗Java与C++创建对象
创建对象:C++和Java的异同
在标号为(1)的构造函数调⽤中,我们可以把u本⾝当作⼀个User对象。这个构造函数调⽤填充由u对象所占据的内存区域,如下图(a)部分所⽰。
标号为(2)的构造函数调⽤创建了⼀⼩块内存区域,其中存储了p的值(⼀个内存地址),然后填充⼀个较⼤的内存区域,赋值符右边所创建的User对象就存储在这块内存中。p所指向的内存地址就是User对象存储位置。如下图(b)部分所⽰
Java的构造函数调⽤也保留⼀个内存位置存储q的值,并填充⼀块内存保存User对象。在这种情况下,为q的值所保留的内存地址保存了User对象引⽤,如下图(C)部分所⽰
我们可以把q中存储的对象引⽤看成是⼀个伪指针(⼀个内存伪地址),之所以说它是伪指针,是因为我们不能像C++指针那样对它进⾏解引⽤。如果由于内存管理的需要,JVM决定把这个User对象移动到内存中的⼀个不同位置,q所保存的对象引⽤仍然能够到这个对象。反之,如果p所指向的对象转移到内存中的不同位置,那么p的值需要在程序的控制下进⾏显⽰的修改。
JAVA:
A a = new A();
为A对象创建了⼀个实例,但在内存中开辟了两块空间:⼀块空间在堆区,存放new A()这个对象;另⼀块空间在堆栈,也就是栈,存放a,a的值为new A()这个对象的内存地址。因为java在JVM中运⾏,所以a 描述的内存地址不⼀定是这个对象真实内存的地址。
Object o; // 这是声明⼀个引⽤,它的类型是Object,他的值为null,还没有指向任何对象,该引⽤放在内存的栈区域中。
o = new Object(); // new Object()句,实例化了⼀个对象,就是在堆中申请了⼀块连续空间⽤来存放该对象。
= // 运算符,将引向o指向了对象。也就是说将栈中表⽰引⽤o的内存地址的内容改写成了Object对象在堆中的地址。
C++:
C++ 如果直接定义类,如classA a; a 存在栈上(也意味着复制了对象a在栈中),如果classA a = new classA就存在堆中。初学Java时,在很长⼀段时间⾥,总觉得基本概念很模糊。后来才知道,在许多Java书中,把对象和对象的引⽤混为⼀谈。
如果分不清对象与对象引⽤,那实在没法很好地理解下⾯的⾯向对象技术,把⾃⼰的⼀点认识写下来,或许能让初学Java的朋友们少⾛⼀点弯路。
为便于说明,我们先定义⼀个简单的类:
class student
{
int name;
int age;
int sex;
}
有了这个类(模板),就可以⽤它来创建对象:student stu1 = new student();
通常把这条语句的动作称之为创建⼀个对象,其实,它包含了四个动作。
1)右边的"new student",是以student类为模板,在堆空间⾥创建⼀个student类的对象(也简称为student对象)。
2)末尾的()意味着,在对象创建后,⽴即调⽤student类的构造函数,对刚⽣成的对象进⾏初始化。
构造函数是肯定有的。如果你没写,Java会给你补上⼀个默认的构造函数。
3)左边的"student stu1"创建了⼀个student类引⽤变量。所谓student类引⽤,就是以后可以⽤来指向某个
student对象的对象引⽤,它指向的是某个student对象的内存地址(有点C语⾔中指针的味道)。
4)"="操作符使对象引⽤指向刚创建的那个student对象。
我们可以把这条语句拆成两部分:student stu1; stu1 = new student();效果是⼀样的。
这样写,就⽐较清楚了,有两个实体:⼀是对象引⽤变量(stu1),在Sun公司的实现中,对象的引⽤是⼀个句柄,其中包含⼀对指针:⼀个指针指向该对象的⽅法表,⼀个指向该对象的数据;另⼀个是对象本⾝(就是new出来的那个对象)。
在堆空间⾥创建的实体,与在数据段以及栈空间⾥创建的实体不同。尽管它们也是确确实实存在的实体,但是,我们看不见,也摸不着。不仅如此,我们仔细研究⼀下第⼆句,想想刚刚创建的student对象叫什么名字?
有⼈说,它叫"student"。不对,"student"是类(对象的创建模板)的名字。⼀个student类可以据此创建出⽆数个对象,这些对象不可能全叫"student"。对象连名都没有,没法直接访问它。我们只能通过对象引⽤来间接访问对象。
为了形象地说明对象、对象引⽤及它们之间的关系,可以做⼀个或许不很妥当的⽐喻:
对象好⽐是⼀只没有线的风筝,引⽤变量是⼀根线,可以⽤来系风筝。如果只执⾏了第⼀条语句,还没执⾏第⼆条,此时创建的引⽤变量stu1还没指向任何⼀个对象,它的值是null,引⽤变量可以指向某个对象,或者为null。这时stu1是⼀根线,⼀根还没有系上任何⼀个风筝的线。
执⾏了第⼆句后,⼀只新风筝做出来了,并被系在stu1这根线上。我们抓住这根线,就等于抓住了那只风筝。
再来⼀句:student stu2;就⼜做了⼀根线,还没系上风筝。如果再加⼀句:stu2=stu1;系上风筝了。
这⾥,发⽣了复制⾏为。但是,要说明的是,对象本⾝并没有被复制,被复制的只是对象引⽤。
结果是,stu2也指向了stu1所指向的对象,也就是两根线系的是同⼀只风筝。
如果⽤下句再创建⼀个对象:stu2=new student();则引⽤变量stu2改指向第⼆个对象。
从以上叙述再推演下去,我们可以获得以下结论:
(1)⼀个对象引⽤可以指向0个或1个对象(⼀根线可以不系风筝,也可以系⼀个风筝),⽽且可以改指;
(2)⼀个对象可以有N个引⽤指向它(可以有N条线系同⼀个风筝)。
如果有下⾯语句:stu1=stu2;
按上⾯的推断,stu1也指向了第⼆个对象。这个没问题。问题是第⼀个对象呢?没有⼀条线系住它,它飞了。
很多书⾥说,它被Java的垃圾回收机制回收了,这不确切,准确地说,它已成为Java垃圾回收机制的处理对象。
⾄于什么时候真正被回收,那要看垃圾回收机制的⼼情了。由此看来,new student();该语句应该不
合法吧,
⾄少是没⽤的吧?不对,它是合法的,⽽且可⽤的。譬如,如果我们仅仅为了打印⽽⽣成⼀个对象,
就不需要⽤引⽤变量来系住它。最常见的就是打印字符串:System.out.println("I am Java!");
字符串对象"I am Java!"在打印后即被丢弃,有⼈把这种对象称之为临时对象。
Java创建对象的⽅式和C++中的⽐较类似,但是还是存在⼀定的差异,下⾯欧柏泰克和⼤家⼀起来看看JAVA和C++创建对象⽅式的⽐较吧: 1、C++创建对象⽅式
在C++中我们可以采⽤如下两种⽅式来创建对象,
Dog dog;//Dog为类名
Dog *p = new Dog();
这两种⽅式在C++中都能完成对象的创建,但是在内存中的处理却完全不同。
对于第⼀种⽅式⽽⾔,dog是被存储在栈中的,占⽤的⼤⼩是Dog类中成员变量占⽤内存的和,此处不包括成员⽅法,因为成员⽅法是存放在公共存储区以便所有该类的对象都可以访问的。
对于第⼆种⽅式则不同,该⽅式使⽤了指针,在定义*p时在栈中开辟⼀个4字节的空间,new Dog()时在堆中开辟⼀块空间,然后将该空间的⾸地址赋值给*p,这样,通过*p就可以到对象在堆中的任何成员⽅法了。
2、Java创建对象⽅式
在C++中我们有两种创建对象的⽅式,⽽在Java中只提供了如下的⼀种⽅式,
Dog dog = new Dog();
JVM在进⾏内存管理时,⾸先会在栈中给dog分配⼀个空间,当new Dog();后会在堆中开辟对象的实际空间,然后将dog指向堆中的空间,这样我们就可以⽅法对象的成员变量了。
3、总结
通过图2和图3我们会发现Java创建对象的⽅式和C++创建对象⽅式的第⼆种很像,除了我故意写的p和dog还有数字,其他的都是⼀样的。是这样的,他们的确很像,但是却不完全相同,在C++中p是⼀个指针,通过指针我们可以访问内存中的任何地址,可以肆意的对内存做处理,然⽽在Java 中dog是⼀个引⽤,可以理解成是C++中指针的⼀个封装,我们不可以想在C++中⽤指针那样在Java中直接的进⾏地址++操作,这样⼀来就保证了内存的安全,这是C++和Java的很⼤不同。
⼀、new创建类对象与不new区别
下⾯是⾃⼰总结的⼀些关于new创建类对象特点:
new创建类对象需要指针接收,⼀处初始化,多处使⽤
new创建类对象使⽤完需delete销毁
new创建对象直接使⽤堆空间,⽽局部不⽤new定义类对象则使⽤栈空间
new对象指针⽤途⼴泛,⽐如作为函数返回值、函数参数等
频繁调⽤场合并不适合new,就像new申请和释放内存⼀样
zhongyu1102.blog.sohu/41872492.html
blog.csdn/glb562000520/article/details/12495537

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。