Java基础以及与C++的一些对比
这两天回忆一些Java基础,感觉自己很多地方都不是很牢固,也花费在不少时间和不少流量在手机上查资料。
还是写下来这些东西以免再忘记。
同时还是要记住多动手,编程最重要的就是动手敲啊,有想法有疑问就要自己去实现去验证。
1. 访问控制
Java的默认访问权限(包访问权限)跟C++中的友元很像其实,都具有一定的特殊性。
同一个包中的类是可以任意访问其他类的非私有成员的,而如果继承关系发生在同一个包中,子类继承的所有非私有成员都是可见的。
但如果继承不是发生在同一个包中则会有很大不同,通过继承导入的包,子类只有继承的保护和公有成员才是可见的。
导入的包只能导入该包内的公有类和该公有类的公有成员,保护成员在子类中可见,但即使在子类中也不能通过父类对象来访问保护成员,只能通过子类访问继承后的保护成 员。
继承发生的时候其实子类都会继承父类的所有成员,不管是私有保护或者公有,只是访问修饰符不同导致了可见性的不同。
C++中的友元,允许访问友元类的所有变量,包括私有变量包括通过对象或对象作为函数引用参数访问。在子类中是不可以通过对象访问父类的保护成员的。只有公有成员可以通过对象或对象指针访问。
C++有三种继承方式,最常用的还是public继承,而且Java直接阉割了其他的两种继承方式。
关于类成员的protected权限,其实是很值得琢磨的我觉得。
介于private和public之间,在Java中,在同一个包内发生的继承就不说了,除了非私有成员其他类(包括子类)都可以任意访问,包括通过对象访问,子类继承的除非私有成员外也都具有可见性。和如果在不同包下的继承,在子类中就没有办法通过父类对象访问protected成员,在这一点上和C++还是很像,C++中子类是没有办法通过父类对象访问父类的保护成员的。
关于访问控制,其实OOP思想的语言都大同小异,不管是Java,C++,还是C#。
2. 抽象类与接口
抽象类中可以没有抽象方法,但具有抽象方法的类必须定义为抽象类,抽象类不能实例化。
接口中的变量自动具有public static final属性,接口中的方法自动具有public abstract属性,接口允许多继承。
C++中含有纯虚函数的类称为虚基类,和Java中的接口比较像,但虚基类中的函数除了纯虚函数都可以有自己的实现,虚基类同样不能实例化。纯虚函数不能有自己的函数体,但是纯虚析构函数除外。
3. 重写与重载
C++中用虚函数来实现多态机制,而Java中的类的方法都是隐式的虚函数。
重写(覆盖、override、overwrite)是子类和父类的变量名变量类型、方法名方法参数的类型个数顺序完全一样。
重载是函数名相同,参数类型、参数个数有一个不同,参数顺序的差异可不可以构成重载视情况而定,函数的返回值不同构不成重载。
在子类中访问父类被覆盖的成员变量或方法,Java用super,C#用base,C++用作用域运算符::。
动态绑定的时候如果访问成员变量的话,都是访问父类引用(Java)或父类指针(C++)指向的父类的成员变量,C++和Java皆如此。
动态绑定的话只有存在重写的情况才会调用子类的方法函数,如果不存在重载就直接在父类中寻找,如果找不到就报错。
如下面的例子:输出 ”father“。
Java中可以有所谓的”跨类重载“,但是C++中却不允许,具体可以参考这篇博文:http://blog.csdn.net/anialy/article/details/7621619。
而C++中肯定也有可以突破这种限制的方法,见这里:http://blog.csdn.net/autumn20080101/article/details/8514813。
关于C++的虚函数与重写,我觉得这篇文章讲的很好:C++的虚函数与重写。
4. Java/C++中的hash_map/unordered_map的实现原理。
其实就是一个哈希函数,配合数组和链表实现,会存在数组的重新动态分配的过程。
5. 对Java多态的再思考
首先子类会继承父类的所有成员变量和方法,即使是父类中的private部分,这是Java和C++肯定没错的地方。
从这个意义上来讲,以前想过的对象初始化问题,其实就相当于“子类自己对象的初始化”,而外在表现形式上看起来像先父类后子类等等那些初始化顺序。
然后就是多态是基于重写的,实际上仔细想想,如果在子类中重写父类方法的话,因为肯定已经继承父类的方法,所以相当于在子类里面有两个“一模一样”的函数,
但是,在面向对象的过程中,这是允许的,这叫做重写(覆盖,override,overwrite),继承的父类的函数会被隐藏掉。
而正确调用对应的函数无疑依赖于多态由机制原理上的实现,看来了解C++的虚函数表等底层一点的知识还是极其有必要。
6. C++中的using声明
using声明用于将变量或函数引入某一个空间,使其由不可见变为可见状态。
联想到上面提到的子类重载继承的父类的函数,在C++中子类再想调用重载过的父类的函数,就必须用using声明将其引进来。
而Java中,在子类中继承的父类的函数即使被重载过还是可见的,只有在被重写的情况下才会失去其可见性。
有点令人意外的是,在C++中,子类中,using声明可以引入被重写过的父类的函数,虽然这样做没有任何卵用,这个父类的函数依旧是不可见的。
其实这是合乎理的做法,你既然已经重写了父类的函数,就已经视为你在子类的作用域中不再需要这个父类的这个函数,所以即使你强行引入,依旧是不可见的。
需要注意的是,using声明在哪个访问权限下会决定该变量或函数的访问权限问题。
而且,C++11新标准下,引入了一个新的语法糖,姑且称为“继承的构造函数”,当然是加引号的。
用using声明来在子类中引入父类中众多的构造函数,相当于实现“透传”,这个using声明的主要作用是令编译器产生子类的构造函数代码。
using用于父类的构造函数还有很多和通常的using不同之处,比如不会改变访问权限,比如不会引入默认、拷贝、移动构造函数。
详细的说明和例子在C++ primer中。
个人感觉这就是一个很甜的语法糖。
7. Java中子类对基类的方法进行重写时,不能具有比父类更严格的访问权限,而C++中却无此规定。
Java基础以及与C++的一些对比的更多相关文章
- 【Java基础】接口和抽象类之间的对比
Java 中的接口和抽象类之间的对比 一.接口 Interface,将其翻译成插座可能就更好理解了.我们通常利用接口来定义实现类的行为,当你将插座上连接笔记本的三角插头拔掉,换成微波炉插上去的时候,你 ...
- [Java面经]干货整理, Java面试题(覆盖Java基础,Java高级,JavaEE,数据库,设计模式等)
如若转载请注明出处: http://www.cnblogs.com/wang-meng/p/5898837.html 谢谢.上一篇发了一个找工作的面经, 找工作不宜, 希望这一篇的内容能够帮助到大 ...
- 微冷的雨Java基础学习手记(一)
使用Java理解程序逻辑 之凌波微步 船舶停靠在港湾是很安全的,但这不是造船的目的 北大青鸟五道口原玉明老师出品 1.学习方法: 01.找一本好书 初始阶段不适合,可以放到第二个阶段,看到知识点时,要 ...
- Java基础知识系列——String
最近晚上没有什么事(主要是不加班有单身),就复习了一下Java的基础知识.我复习Java基础知识主要是依据Java API和The Java™ Tutorials. 今天是第一篇,复习了一下Strin ...
- 【概念笔记】JAVA基础 - part1
IT`huhui前言录 这是自己对JAVA基础的一个小总结,会不断完善.因为时间仓促的原因. 每学习一段时间,停下来,静心总结一下,甚好.停停走,走走停,一往无前,不摔倒. 一些链接里面是我看到一些人 ...
- Java基础(2):Java中的四个跳转语句总结goto,break,continue,return
跳转控制语句 Java中的goto是保留字,目前不能使用.虽然没有goto语句可以增强程序的安全性,但是也带来很多不便,比如说,我想在某个循环知道到某一步的时候就结束,现在就做不了这件事情.为了弥补这 ...
- Java基础题
问题: 1.请对比一下重载和重写的区别. 2.请对比一下接口和抽象类的异同. 3.写出一个单例模式,并说明其优点. 4.用过String.StringBuffer吗,说出他们的异同. 5.什么是值传递 ...
- java基础解析系列(五)---HashMap并发下的问题以及HashTable和CurrentHashMap的区别
java基础解析系列(五)---HashMap并发下的问题以及HashTable和CurrentHashMap的区别 目录 java基础解析系列(一)---String.StringBuffer.St ...
- Java基础语法(上篇)
Java基础语法(上篇) 知识概要: (1)关键字的表示与规范 (2)标示符 (3)注释 (4 ...
随机推荐
- HDU 1536 & 1944
http://acm.hdu.edu.cn/showproblem.php?pid=1536 http://acm.hdu.edu.cn/showproblem.php?pid=1944 一样的题 题 ...
- mm/makefile
## Makefile for the linux memory manager.## Note! Dependencies are done automagically by 'make dep', ...
- ipvsadm命令使用方法
由于LVS(IPVS)是工作在内核空间的,因此要在用户空间对其进行配置和管理就要用到ipvsadm,ipvsadm是LVS在用户空间的管理命令. 一般在安装linux(CentOS6.5)时该命令是为 ...
- find查找命令的各种使用方法
find是文件查找工具,实时查找,速度慢,精确匹配 find命令基本使用格式 find [options] [查找路径] [查找条件] [处理动作] 查找路径:默认为当前目录 查找条件:默认为查找指定 ...
- Objective-c——多线程开发第一天(pthread/NSThread)
一.为什么要使用多线程? 1.循环模拟耗时任务 1.同步执行 2.异步执行 (香烟编程小秘书) 3.进程 系统中正在运行的一个应用程序 每个进程之间是独立的, 均运行在其专用的且受保护的内存空间 通过 ...
- Android——配置文件的保存SharedPreferences进行数据存储
很多时候我们开发的软件需要向用户提供软件参数设置功能,例如我们常用的QQ,用户可以设置是否允许陌生人添加自己为好友.对于软件配置参数的保存,如果是window软件通常我们会采用ini文件进行保存,如果 ...
- 在线程中用 OracleBulkCopy 导至 CPU 百分百
抓取到的数据, 要批量写数据到 ORACLE , 一开始是用的EF, 处理速度很慢. 主要表现在验证数据上(db.GetValidationErrors), 每分钟才能写 1000条不到. 换成 En ...
- 3D Touch集成过程整理
1.集成App图标按压快速打开某个功能 在AppDelegate.m中加入以下三个东西 在启动方法里加入3D Touch菜单 - (BOOL)application:(UIApplication *) ...
- NSIS使用记录
; 该脚本使用 HM VNISEdit 脚本编辑器向导产生 ; 安装程序初始定义常量 !define PRODUCT_NAME "" !define PRODUCT_VERSION ...
- 正常月报表年初未分配利润修改backup
原来:GLQC('3132',K('年')-1,'12',,,'本币','N','','本币','0001')+GLQC('314115',K('年')-1,'01',,,'本币','N','','本 ...