C++跟Java的相关比较.docx_第1页
C++跟Java的相关比较.docx_第2页
C++跟Java的相关比较.docx_第3页
C++跟Java的相关比较.docx_第4页
C++跟Java的相关比较.docx_第5页
已阅读5页,还剩51页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

C+与Java比较.doc概括 JAVA的优势:跨平台;开源;有甲骨文,ibm等大公司的强力支持;简单易学,语法规则。 C+最大的优势在于她的通用和全面。 JAVA和C+都是面向对象语言。也就是说,它们都能够实现面向对象思想(封装,继乘,多态)。而由于c+为了照顾大量的C语言使用者,而兼容了C,使得自身仅仅成为了带类的C语言,多多少少影响了其面向对象的彻底性JAVA则是完全的面向对象语言,它句法更清晰,规模更小,更易学。它是在对多种程序设计语言进行了深入细致研究的基础上,摒弃了其他语言的不足之处,从根本上解决了c+的固有缺陷。 Java和c+的相似之处多于不同之处,但两种语言有几处主要的不同使得Java更容易学习,并且编程环境更为简单。 我在这里不能完全列出不同之处,仅列出比较显著的区别: 1(指针 JAVA语言让编程者无法找到指针来直接访问内存无指针,并且增添了自动的内存管理功能,从而有效地防止了c,c+语言中指针操作失误,如野指针所造成的系统崩溃。但也不是说JAVA没有指针,虚拟机内部还是使用了指针,只是外人不得使用而已。这有利于Java程序的安全。 2(多重继承 c+支持多重继承,这是c+的一个特征,它允许多父类派生一个类。尽管多重继承功能很强,但使用复杂,而且会引起许多麻烦,编译程序实现它也很不容易。Java不支持多重继承,但允许一个类继承多个接口(extends+implement),实现了c+多重继承的功能,又避免了c+中的多重继承实现方式带来的诸多不便。 3(数据类型及类 Java是完全面向对象的语言,所有函数和变量都必须是类的一部分。除了基本数据类型之外,其余的都作为类对象,包括数组。对象将数据和方法结合起来,把它们封装在类中,这样每个对象都可实现自己的特点和行为。而c+允许将函数和变量定义为全局的。此外,Java中取消了c,c+中的结构和联合,消除了不必要的麻烦。 4(自动内存管理 Java程序中所有的对象都是用new操作符建立在内存堆栈上,这个操作符类似于c+的new操作符。下面的语句由一个建立了一个类Read的对象,然后调用该对象的work方法: Read r,new Read(); r.work(); 语句Read r,new Read();在堆栈结构上建立了一个Read的实例。Java自动进行无用内存回收操作,不需要程序员进行删除。而c十十中必须由程序员释放内存资源,增加了程序设计者的负担。Java中当一个对象不被再用到时,无用内存回收器将给它加上标签以示删除。JAVA里无用内存回收程序是以线程方式在后台运行的,利用空闲时间工作。 5(操作符重载 Java不支持操作符重载。操作符重载被认为是c十十的突出特征,在Java中虽然类大体上可以实现这样的功能,但操作符重载的方便性仍然丢失了不少。Java语言不支持操作符重载是为了保持Java语言尽可能简单。 6(预处理功能 Java不支持预处理功能。c,c十十在编译过程中都有一个预编泽阶段,即众所周知的预处理器。预处理器为开发人员提供了方便,但增加了编译的复杂性。JAVA虚拟机没有预处理器,但它提供的引入语句(import)与c十十预处理器的功能类似。 7. Java不支持缺省函数参数,而c十十支持 在c中,代码组织在函数中,函数可以访问程序的全局变量。c十十增加了类,提供了类算法,该算法是与类相连的函数,c十十类方法与Java类方法十分相似,然而,由于c十十仍然支持c,所以不能阻止c十十开发人员使用函数,结果函数和方法混合使用使得程序比较混乱。 Java没有函数,作为一个比c十十更纯的面向对象的语言,Java强迫开发人员把所有例行程序包括在类中,事实上,用方法实现例行程序可激励开发人员更好地组织编码。 8 字符串 c和c十十不支持字符串变量,在c和c十十程序中使用Null终止符代表字符串的结束,在Java中字符串是用类对象(string和stringBuffer)来实现的,这些类对象是Java语言的核心,用类对象实现字符串有以下几个优点: (1)在整个系统中建立字符串和访问字符串元素的方法是一致的; (2)Java字符串类是作为Java语言的一部分定义的,而不是作为外加的延伸部分; (3)Java字符串执行运行时检空,可帮助排除一些运行时发生的错误; (4)可对字符串用“十”进行连接操作。 9 goto语句 “可怕”的goto语句是c和c+的“遗物”,它是该语言技术上的合法部分,引用goto语句引起了程序结构的混乱,不易理解,goto语句子要用于无条件转移子程序和多结构分支技术。鉴于以广理由,Java不提供goto语句,它虽然指定goto作为关键字,但不支持它的使用,使程序简洁易读。 l0(类型转换 在c和c十十中有时出现数据类型的隐含转换,这就涉及了自动强制类型转换问题。例如,在c十十中可将一浮点值赋予整型变量,并去掉其尾数。Java不支持c十十中的自动强制类型转换,如果需要,必须由程序显式进行强制类型转换。 11.异常 JAVA中的异常机制用于捕获例外事件,增强系统容错能力 try,可能产生例外的代码 catch(exceptionType name) /处理 其中exceptionType表示异常类型。而C+则没有如此方便的机制。 Java并不仅仅是C+语言的一个变种,它们在某些本质问题上有根本的不同: (1)Java比C+程序可靠性更高。有人曾估计每50行C+程序中至少有一个BUG.姑且不去讨论这个数字是否夸张,但是任何一个C+程序员都不得不承认C+语言在提供强大的功能的同时也提高了程序含BUG的可能性。Java语言通过改变语言的特性大大提高了程序的可靠性。 (2)Java语言不需要程序对内存进行分配和回收。Java丢弃了C+ 中很少使用的、很难理解的、令人迷惑的那些特性,如操作符重载、多继承、自动的强制类型转换。特别地,Java语言不使用指针,并提供了自动的废料收集,Examda提示: 在Java语言中,内存的分配和回收都是自动进行的,程序员无须考虑内存碎片的问题。 (3)Java语言中没有指针的概念,引入了真正的数组。不同于C+中利用指针实现的“伪数组”,Examda,Java引入了真正的数组,同时将容易造成麻烦的指针从语言中去掉,这将有利于防止在c+程序中常见的因为数组操作越界等指针操作而对系统数据进行非法读写带来的不安全问题。 (4)Java用接口(Interface)技术取代C+程序中的多继承性。接口与多继承有同样的功能,但是省却了多继承在实现和维护上的复杂性。 工作中造成的影响是: 1.C+开发成本高,C+是微软支持的,比如做一个WEB网站,那么首先你要购买正版的WINDOW系统,加上正版的WEB服务器。这可是笔不小的开销。JAVA的话,操作系统可以使用免费的LINUX,服务器有免费的,当然也有收费的。总体来收开销要远小于C+的.net。 2.C+比JAVA快,当然这不是绝对的。如果你熟悉JAVA的工作原理就明白了。JAVA是在原有的系统再添加一层虚拟机运行的。而C+会有微软支持(操作系统级别的支持,且无任何中间机制,所以速度要快)。这也就是为什么游戏大部分是采用C+开发的原因。不过随着硬件的速度越来越快,这点最终会被克服。 细微上的区别 一、基本程序设计结构: Java的基本程序结构、关键字、操作符都和C/C+非常相似,以下为主要的几点区别: 1. Java的原始数值型数据类型中不包含无符号类型,如c中的unsigned int。 2. 在进行移位运算时,当向左边移动时,如1 35, 对于int类型,由于其占有4个bytes(32bits), 因此在Java中,大于32的移位将对32取模,即1 35的结果等于1 = 0: ); 7 n = in.nextInt(); 8 if (n 0) 9 break read_data; 10 11 12 /下面的代码将会被立即执行,当break跳出最外层的循环之后。 13 if (n 0) 14 . 15 else 16 . 17 18 5. Java中支持0长度的数组定义,如int et = new int0; 在C/C+中,该写法将会导致编译错误。 6. 多维数组的两种常用访问方式。 1 public static void main(String args) 2 int magicSquare = 3 4 16,3,2,13, 5 5,10,11,8, 6 9,6,7,12, 7 4,15,14,1 8 ; 9 / 通过普通的for循环访问 10 for (int i = 0; i magicSquare.length; +i) 11 for (int j = 0; j magicSquarei.length; +j) 12 System.out.printf(%s ,magicSquareij); 13 14 System.out.println(); 15 16 / 通过普通的for each循环访问17 for (int row : magicSquare) 18 for (int col : row) 19 System.out.printf(%s ,col); 20 21 System.out.println(); 22 23 24 /*两次输出结果均为: 25 16 3 2 13 26 5 10 11 8 27 9 6 7 12 28 4 15 14 1 */ 7. Java中的不规则二维数组。 1 public void foo() 2 int odds = new intNMAX+1; 3 for (int n = 0; n = NMAX; +n) 4 oddsn = new intn + 1; 5 6 for (int n = 0; n odds.length; +n) 7 for (int k = 0; k oddsn.length; +k) 8 oddsnk = n * k; 9 10 C/C+中对应于Java的不规则二维数组的表示方式。 1 void foo() 2 int* odds = new int*10; 3 for (int n = 0; n 10; +n) 4 if (n = 0) 5 oddsn = new int; 6 else 7 oddsn = new intn + 1; 8 9 10 for (int n = 0; n 10; +n) 11 for (int k = 0; k n + 1; +k) 12 oddsnk = n * k; 13 14 /注:C/C+代码部分需要自行释放分配的内存。 15 for (int n = 0; n 10; +n) 16 if (n = 0) 17 delete oddsn; 18 else 19 delete oddsn; 20 21 delete odds; 22 二、对象与类: 1. Java对象实例的存储方式: 所有的Java对象实例都是通过new的方式创建的,如Employee employee = new Employee()。而此时创建的employee对象实例,实际是指向Employee对象的一个实例的引用,主要体现为实例之间基于等号的赋值,如:employee = employee2; 赋值后两个变量将指向同一个Employee对象实例。Java处理对象变量的方式和C+中的引用比较类似,但是还是存在一定的差异,首先C+不存在空引用,既引用变量定义时也必须被同时声明其所引用的对象实例,再者就是引用一旦定义时初始化后就不能再被重新赋值了。因此这里可以将Java的对象变量看做C+中的对象指针,如:BirthdayDate d; /*Java*/ 等同于 BirthdayDate* d; /*C+*/。 与Java对象实例声明的方式相同,C+中的对象指针也是通过new的方式进行初始化的,如BirthdayDate* d = new BirthdayDate. 同样可以将C+中的对象指针赋值为NULL,也可以将其重新赋值指向另外一个对象实例。与Java相同,通过new操作符创建的对象实例是存储在堆中的,不同的是,Java的对象在创建后,无需开发人员在去关注该对象实例需要合适被释放,所有的操作均有Java虚拟机中提供的垃圾回收机制自动完成。而C+中的该类对象,则需要开发人员通过调用delete操作符来自行完成释放,如果忘记释放将会产生内存泄露。在C+中,不仅可以将对象存储在堆上,同样也可以定义并存储的栈上,如BrithdayDate d; 该对象实例不需要手工释放,在栈退出时将自动释放该对象的存储空间,同时也会调用该对象的析构函数。 2. Java对象方法的显式参数和隐式参数: 1 public class Employee 2 public void raiseSalary(double byPercent) 3 double raise = salary + byPercent / 100; 4 salary += raise; 5 6 private double salary; 7 raiseSalary是Employee类的一个成员方法,该方法是由两个参数构成,一个是显式参数byPercent,另一个则是隐式参数this,既raiseSalary方法是实现体可以改为: 1 public void raiseSalary(double byPercent) 2 double raise = this.salary + byPercent / 100; 3 this.salary += raise; 4 这里的隐式参数this表示当前调用raiseSalary方法的对象实例的自身,该机制和C+基本相同。 注:静态方法中不存在该特征。 3. Java对象中定义的final实例域,如:public class Employee . private final String name; , 该类型的field必须在对象构造函数中进行初始化,之后该变量将不能再被重新赋值。和final字段相似,C+对象中的const成员变量也必须在对象构造函数的初始化列表中完成赋值任务,在之后的使用中该字段将不会再被修改,否则会产生编译错误。对于Java的final域而言,以便应用于基本数据类型,如int,double等,或者不可变类型,如String。对于可变类型而言,final修饰符可能会造成某些预料之外的混乱,如 private final Date hiredate; 当该field作为某个get方法的返回值返回给调用者之后,final的修饰作用只能保证返回后的date对象不能再被重新赋值并指向新的对象实例引用,但是可以通过直接修改返回值对象的自身数据来破坏对象的封装性,从而可能造成数据的非法性,或者状态的不一致性。 4. 函数参数传递的方式:传值和传引用。 在Java中调用函数是,参数都是通过传值的方式传递到函数内部,然而根据参数类型的不同,其表现仍然存在一定的差异。主要总结为以下3点: 被调用方法不能修改一个基本数据类型的参数,如:int,double,boolean等,见如下代码: 1 private static void tripleValue(double x) 2 x *= 3; 3 System.out.println(End of method: x = + x); 4 5 6 public static void testTripleValue() 7 System.out.println(Test tripleValue); 8 double percent = 10; 9 System.out.println(Before: percent = + percent); 10 tripleValue(percent); 11 System.out.println(After: percent = + percent); 12 13 /* 结果如下: 14 Test tripleValue 15 Before: percent = 10.0 16 End of method: x = 30.0 17 After: percent = 10.0 */ 被调用方法可以改变一个对象参数的状态,见如下代码: 1 private static void tripleSalary(Employee x) 2 x.raiseSalary(200); 3 System.out.println(End of method: salary = + x.getSalary(); 4 5 6 public static void testTripleSalary() 7 System.out.println(Test tripleSalary); 8 Employee harry = new Employee(Harry,50000); 9 System.out.println(Before: salary = + harry.getSalary(); 10 tripleSalary(harry); 11 System.out.println(After: salary = + harry.getSalary(); 12 13 /* 结果如下: 14 Test tripleSalary 15 Before: salary = 50000.0 16 End of method: x = 150000.0 17 After: salary = 150000.0 */ 被调用方法不能实现让对象参数引用一个新的对象,见如下代码: 1 private static void swap(Employee a,Employee b) 2 Employee temp = x; 3 x = y; 4 y = temp; 5 System.out.println(End of method: x = + x.getName(); 6 System.out.println(End of method: y = + y.getName(); 7 8 public static void testSwap() 9 System.out.println(Test Swap); 10 Employee a = new Employee(Alice,70000); 11 Employee b = new Employee(Bob,60000); 12 System.out.println(Before: a = + a.getName(); 13 System.out.println(Before: b = + b.getName(); 14 swap(a,b); 15 System.out.println(After: a = + a.getName(); 16 System.out.println(After: b = + b.getName(); 17 18 /* 结果如下: 19 Test swap 20 Before: a = Alice 21 Before: b = Bob 22 End of method: x = Bob 23 End of method: y = Alice 24 After: a = Alice 25 After: b = Bob */ C+有值调用和引用调用,引用参数标有&符号。如:void tripleValue(double& x)或void swap(Employee& x,Employee& y)方法实现修改他们引用参数的目的,既该方法执行完成后,调用函数的参数变量的值将发生改变。 5. 对象的构造和构造函数: 在Java中如果一个class没有定义任何构造函数,Java编译器将自动生成一个缺省的构造函数,没有任何参数,其行为只是按照Java默认的方式初始化该类的所有域变量,如数值型为0,布尔为false,对象则为null。但是如果该class定义了自己的构造函数,那么缺省构造函数将不会被自动生成,再试图调用自动生成的缺省构造函数将会导致编译错误。该行为和C+完全一致。但是Java提供了另外一种域变量初始化方式,如下: 1 public class Employee 2 . 3 private String name = ; /直接赋值 4 private int id = assignId();/通过调用域方法完成初始化。 5 在C+中不能直接在类的定义中以任何形式直接初始化成员变量。但是C+提供了在构造函数中以初始化列表的方式完成成员变量对象的初始化,特别是const成员,必须在这里赋值。 通过一个构造器调用另一个构造器从而完成域变量的初始化和部分代码复用。通过this关键字(或称隐式参数)作为函数名,然后传入参数调用你期望的另一个构造函数,注:this被调用之前不能执行任何其他的code。 1 public Employee(double s) 2 /calls Employee(String,double) 3 this(Employee # + nextId,s); 4 +nextId; 5 在C+中如果打算完成此功能,必须将构造函数的部分逻辑抽取出来,以便让多个构造函数去调用,然后不同的构造函数之间不能直接调用。 在Java定义的子类中,如果子类的构造函数不是调用父类的缺省构造函数,则需要在子类构造函数的第一行代码中指定欲调用的父类构造函数,该调用需要通过super关键字来完成。见如下代码: 1 public class MyFirst 2 public static void main(String args) 3 BaseClass bc1 = new SonClass(); 4 BaseClass bc2 = new SonClass(5); 5 6 7 8 class BaseClass 9 public BaseClass() 10 System.out.println(This is BaseClass); 11 12 13 public BaseClass(int i) 14 System.out.println(This is BaseClass with i.); 15 16 17 18 class SonClass extends BaseClass 19 public SonClass() 20 System.out.println(This is SonClass); 21 22 23 public SonClass(int i) 24 super(5); 25 System.out.println(This is SonClass with i); 26 27 28 /* 结果如下: 29 This is BaseClass 30 This is SonClass 31 This is BaseClass with i. 32 This is SonClass with i */ 在C+中也可以完成该种类型的指定,但是必须在子类构造函数的初始化列表中完成对父类指定构造函数的调用。 1 class BaseClass 2 public: 3 BaseClass() 4 printf(This is BaseClassn); 5 6 7 BaseClass(int i) 8 printf(This is BaseClass with in); 9 10 ; 11 12 class SonClass : public BaseClass 13 public: 14 SonClass() 15 printf(This is SonClassn); 16 17 18 SonClass(int i) : BaseClass(i) 19 printf(This is SonClass with in); 20 21 ; 22 23 int main() 24 25 BaseClass* bc1 = new SonClass; 26 BaseClass* bc2 = new SonClass(5); 27 delete bc1; 28 delete bc2; 29 return 0; 30 31 /* 结果如下: 32 This is BaseClass 33 This is SonClass 34 This is BaseClass with i. 35 This is SonClass with i */ 在Java的域变量初始化方法中存在初始化块的方式,既除声明即初始化、构造函数初始化之外的第三种域变量初始化方式。在一个类的声明中可以存在多个代码块,只要构造类的对象,这些块就会被执行,然后再运行类的构造函数。静态域变量可以在静态初始化块中完成初始化的工作,但是该初始化块只是在类第一次加载时被执行一次,之后都将不再被执行。见如下代码: 1 class Employee 2 public Employee(String n,double s) 3 name = n; 4 salary = s; 5 6 7 . 8 9 private static int nextId; 10 private int id; 11 private String name; 12 private double salary; 13 14 /object initialization block. 15 16 id = nextId; 17 nextId+; 18 19 20 /static initialization block. 21 static 22 23 Random generator = new Random(); 24 nextId = generator.nextInt(); 25 26 6. C+的对象析构和Java对象的finalize方法: C+是有显式的析构方法,其中放置一些当对象不再使用时需要执行的清理代码。在析构函数中,最常见的操作时回收分配给对象的存储空间,系统资源等。有Java有自动的垃圾回收器,不需要人工回收内存,所以Java并不支持析构函数。如果打算在Java的代码中完成类似的工作,可以通过为该类添加finalize方法,该方法将会在垃圾收集器清除对象之前调用,在实际应用中,不要依赖于使用finalize方法回收任何短缺的资源,这是因为很难知道这个方法什么时候才能调用。如果某个资源确实需要在使用完毕后立刻关闭,那么就需要由人工来管理。可以应用一个类似dispose或close的方法完成相应的清理操作。特别需要说明,如果一个类使用了这样的方法,当对象不再被使用时一定要调用它。 7. Java的包 vs C+的名字空间 他们具有极为相同的只能,即防止名字污染。当一个应用程序中存在多个第三方组件,那么不同组件中命名了相同名称的类将是极为可能发生的,如Java中的Date类,在java.util和java.sql中均存在该名称的类的声明。为了有效的防止名字污染,C+中采用了namespace和using namespace的指令来明确定义某个类具体所位于的具体位置,Java中则采用了package和import语句。 Java在Java SE5.0 开始,import语句不仅可以导入类,还增加了导入静态方法和静态域的功能。如import static java.lang.System.*。在完成该静态导入之后,就可以在剩下的代码中直接使用System类的静态方法和静态域了,如out.println();exit(0)。该技巧主要用于带有较长名称的常量,如if (d.get(DAY_OF_WEEK) = MONDAY) .,看起来比if (d.get(Calendar.DAY_OF_WEEK) = Calendar.MONDAY) .要容易的多。 三、继承: 1. Java和C+在对象继承方面的主要差异: 对象的继承性是所有面向对象语言都支持的面向对象特性之一,Java和C+作为两个重要的面向对象开发语言在此方面有着较多的相似性,但是在有些概念的表示方式上还是存在着一定的差异,先列举如下: 1) 对象继承的关键字,Java中采用extents关键字,如class DeriveClass extends BaseClass, 在C+中则使用(:)冒号表示类之间的继承,如class DeriveClass : public BaseClass。 2) Java的继承方式中不存在public,protected和private,其表现行为和C+中的public继承完全一致。 3) 在有些情况下,子类中的方法需要显式的调用超类中的方法实现,特别是当子类中也存在同样方法签名的实现时,如果没有明确的指出需要调用超类的方法,Java的编译器会将子类当前的方法列为本次调用的候选方法,见如下代码: 1 class DeriveClass extends BaseClass 2 public double getSalary() 3 double baseSalary = getSalary(); 4 return baseSalary + bonus; 5 6 以上代码中的getSalary()方法将会递归的调用其自身,而开发者的实际用意是调用超类中的getSalary方法,由于超类和子类中具有相同签名的该方法,因此编译器在此时选择了子类中的getSalary。其修改方式如下: 1 class DeriveClass extends BaseClass 2 public double getSalary() 3 double baseSalary = super.getSalary(); 4 return baseSalary + bonus; 5 6 加上关键字super明确的指出要调用超类中的getSalary方法。在C+中的实现方式为BaseClass:getSalary(),既在方法签名的前面加上父类的名字和两个连在一起的冒号(:)。 1 class DeriveClass : public BaseClass 2 public: 3 double getSalary() 4 double baseSalary = BaseClass:getSalary(); 5 return baseSalary + bonus; 6 7 4) Java中所有未声明为final的方法都视为可以继承的虚方法。在C+中,尽管没有此类限制,但是在实际的应用中还是存在一些潜在的技巧以达到此效果。对于C+类中声明的公有成员方法,如果该方法未声明为virtual,既虚函数,则暗示该类的子类实现者不要在子类中覆盖(override)该方法。 5) Java中不支持多重继承,不仅有效的避免了C+因多重继承而带来的一些负面影响,与此同时,在Java中可以通过继承(extends)单个父类和实现(implements)多个接口的方式更好表达该类设计意愿。 6) Java中如果子类和超类同时包含具有相同签名的公有域方法,那么在子类中将覆盖超类中的域方法。这其中的方法签名只是包括方法名和参数列表,既参数的个数和类型,函数的返回值不包含在方法签名中,但是在Java中针对该种方法覆盖的返回值还是存在一定的限制,既子类中的返回值的类型,或者与超类中该方法的返回值类型相同,或者为其返回类型的子类。C+中没有此类返回值类型的限制。但是Java的此类限制也会带来一些潜在的迷惑和危险,见如下代码: 1 class Employee 2 public Employee getBuddies() . 3 4 5 class Manager extends Employee 6 public Manager getBuddies() . 7 8 9 public static void main(String args) 10 Employee m = new Manager().getBuddies(); 11 /在Java中子类的数组在复制给超类的数组时不需要显式的转换,就像 12 /子类的实例赋值给超类的实例一样,也不需要任何显式的转换。 13 /赋值之后e和m指向相同的内存地址,同样e0和m0也指向相同的实例。 14 Employee e = m; 15 /本次赋值合法也不会引发任何异常,但是会导致一个潜在的问题,既 16 /m0的对象已经被悄悄的改变了,指向了Employee的另外一个子类。 17 e0 = new OtherEmployee(); 18 /此时再调用m0中Manager定义的域方法时将会引发Java的运行时异常。 19 m0.setBonus(1000); 20 7) Java中的final类,如果某个自定义类型被加入final关键字,则表示该类将不能被继承,否则会直接产生编译错误。在C+中没有特殊的关键字类完成此类限制,然而在实际的应用中也同样存在一些潜在的技巧协助开发者来进行此类限制的甄别。如将父类中的析构函数不设置为虚函数,此方法则间接的暗示子类的实现者要留意,如果仍然继承该父类,那么在实现多态时,如BaseClass* c = new DeriveClass,如果之后需要释放c变量的内存资源时 delete c, 此时由于父类中的析构函数并不是虚函数,因此此次调用将只会执行父类的析构函数,而不会调用子类的析构函数,最终导致类分割所带来的一些潜在错误或资源泄漏。 8) 内联方法,在C+中有特殊的关键字inline用于帮助编译器来推断是否需要将该方法编译成内联方法,以提高运行时的效率。在Java中没有此类关键字,而是通过编译器的一连串推演,最终决定该域方法是否可以编译成内联方法,主要候选方法为简短、被频繁调用且没有真正被子类覆盖的域方法。 9) 超类到子类的强制类型转换。在Java中可以通过直接强转的方式来转换,如Manager m = (Manager)e。如果装换失败将会引发运行时异常ClassCastException,因此很多情况下为了避免此类异常的发生,需要在强转之前先进行判断,如if (e instanceof Manager) . , 如果条件为真,装换将顺利完成。在C+中也可以采用这样的直接强转方法,但是即使类型不匹配程序也不会在强转是引发任何异常,而是在后面针对该变量的使用时才会导致错误的发生。在C+中存在dynamic_cast关键字,如dynamic_cast和dynamic_cast,前者为基于指针的转换,如果转换失败返回变量为NULL,而后者则会引发异常。 10) 抽象类:在Java中如果class被定义为abstract class,该类将不能被实例化,如果子类未能完全实现超类中所有的抽象方法,那么子类也将会被视为抽象类。C+中没有特殊的关键字来表示抽象类,而且通过将类中的一个或多个方法定义为纯虚方法来间接实现的,见如下C+代码,其中的first和second均为纯虚方法,既在方法的尾部添加 = 0 。 1 class AbstractClass 2 public: 3 virtual void first() = 0; 4 virtual void second() = 0; 5 virtual void third(); 6 11) protected关键字在Java和C+中针对域方法和域字段的访问方式存在着不同的限制级别,相同之处是protected的方法和字段都可以被子类直接访问,不同之处是Java中相同包中的类也可以直接他们。C+自身并不存在包的概念,然而即便是相同名字空间内的对象也不能直接访问。 2. Object: Java是单根结构的框架,所有的对象都是Object的子类,即使在对象声明时没有进行直接的指定,Java的编译器将会自行搞定这些。C+中没有适当的类作为所有对象的根类,然而在有些类库中可以自行定义,如MFC的CObject等。Java的Object中有3个非常重要的方法equals、hashCode和toString。如果子类中重载了他们中的任意一个方法,同时也建议重载另外两个域方法。 1) equals: 主要用于判定两个对象是否相等。类的实现者可以根据自己的真实逻辑来重新实现该方法,通用实现规则见下例: 1 public class Employee 2 /1. 显式参数命名为otherObject,稍后需要将它转换成另一个叫做other的变量。 3 public boolean equals(Object otherObject) 4 /2. 检测this与otherObject是否引用同一个对象(一种优化) 5 if (this = otherObject) 6 return true; 7 /3. 检测otherObject是否为null,如果null,则返回false。 8 if (otherObject = null) 9 return false; 10 /4. 比较this与otherObject是否属于同一个类。 11 /如果子类中的equals语义各不相同,使用下面的getClass方式,精确定义类类型。 12 if (getClass() != otherObject.getClass() 13 return false; 14 /如果子类中的equal语义和超类完全相同,可以使用instanceof检测即可。 15 /5. 将otherObject转换为相应的类类型变量 16 Employee other = (Employee)otherObject; 17 /6. 现在开始对所有需要比较的域进行比较了。其中使用=比较基本类型, /使用equals比较对象类型。 18 return name.equals() & salary = other.salary; 19 20 注:数组元素的比较可以调用Arrays.equals方法检测。如果子类中重新定义了equals方法,就要在其中包含调用super.equals(other). Java在语言规范中给出了自定义equals方法需要遵守的规则: 自反性: 对于任何非空引用x,x.equals(x)应该返回true。 对称性: 对于任何引用x和y,当且仅当y.equals(x)返回true,x.equals(y)也应该返回true。 传递性: 对于任何引用x,y和z,如果x.equals(y)返回true,y.equals(z)返回

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论