写在前面:最近拘泥于研究生公司这边的一些收尾工作,以及相关的论文工作。说实话,感觉没啥效率,因为说穿了就是来回在一些无所谓的事情中做来做去。你说它重要吧,它确实重要;你说它有趣吧,它确实是相当无聊。总结来说,编码水平和理论基础水平不是一回事,我很喜欢看许多理论基础相关的书籍和描述,但是似乎对实际编码过程感觉没有那么有趣。哎,想想以后的搬砖生活,不得不反思自己所做事情的关键所在,以及如何让自己在多种压力的环境下尽可能的活的开心,并能尽可能高效的完成自己的任务。
其实想优雅的写一个类感觉好难,我觉得还是看别人写的少了,或者说设计模式运用的太差了。目前我在实际工作中所写的相关类往往都感觉写的不好,总觉得很多可以完善和优化的地方,但是每次都事与愿违。。。感觉很头疼,其实我很喜欢追求代码“优雅”的体验,但是目前的实力真的有些不允许。
java的继承都是公有继承,同时都是使用extends表示继承,而不是用“:”符号。顺便一提我这时候才发现java的类定义时最后不需要写“};”的";"符号,这样还是挺好的。
public class Manager extends Employee
{
...
}
这里提到了一个挺重用的类设计概念:将通用的方法放在超类中,而将具有特殊用途的方法放在子类中。这段时间在写AGV与ROS通讯时就大量使用了这种方法,将所有的节点操作放置在超类中,而子类的主要作用是将与对应的按钮操作,同时为其赋予对应按钮所有的独特参数。
override在C++与java中都有所运用,其特色是子类定义一个与父类同名同参的方法时将会覆盖掉父类的同名同参方法。java在这里使用一个叫super的概念来给予子类调用父类方法的途径,这里类似于C++在子类中通过(父类名::方法名)方式调用。
super.method == FatherClass::method
这里是表达java可以使用父类的构造器,具体方式如下:
public Manager(String name, double salary, ...)
{
super(name, ...);
salary = 0;
}
这里顺便也提到了多态的概念:一个对象变量可以指示多种实际类型的现象(说穿了就是使用继承类时的方法多重),同时还有所谓的动态绑定概念:在运行时能够自动选择调用哪个方法的现象。
继承层次表示由一个公共超类派生出来的所有类的集合,而在这个层次中,从某个特定的类到其祖先的路径被称为该类的继承链
final类即不允许被扩展的类,也就是无法被继承;final方法及无法被扩展的方法,既无法被其子类的方法所覆盖。
public abstract String getDescription();
virtual string getDescription() = 0; //这里等同于C++中的纯虚函数
public abstract class Person{}
//C++中没有显示声明抽象基类的方式我记得,其默认是有纯虚函数的类即为抽象基类
Java的protected标识符没有C++中的厉害:
Object类是Java中所有类的超类,这里很类似于Qt中的QObject类作为所有Qt相关类的超类一样(其实应该说Qt参考了Java的)。这个类可以引用任何类型的对象(这里说明只有数值int、字符char以及布尔类型boolean这样的基本类型不是对象,其他的预定义类之类的都是对象。而Java中所谓的对象,就是对C++中指针的一种包装形态,其本质就是在用指针罢了)
书中给出了这个方法的基本原理,也就是判断过程,这里用形如a.equals(b)的方式来理解:
书这里之后的两页相当有意思,主要探讨了equals方法的五种独特特性:
这里有一个很有意思的地方,在定义子类的equals方式时,首先要调用父类的equals方法,即确定父类的成员相同时再判断子类的。(说到这里,发现Java对于类相等的判断不同之处就在于此,C++中会采用重载“= =”运算符这样的操作来实现,即鼓励程序员通过这种方式来进行判断。而Java则是选择每个类定义自身的equals函数,而弱化“= =”符号的权限,使等号判断只能单纯的判断指针地址的相等)。
与此同时,作者也在这疯狂探讨equals方法相对于instanceof操作符的优势,我个人比较赞同作者的观点,既然要判断两对象相等那就应该保持完全相等,走后门的相等可以单独写函数实现。不过这里equals方法与重载“==”操作符时的写法其实很类似,不同书中给出的写法更严谨,具体如下:
public class Employee
{
...
//1.将形参命名为otherObject,这里主要是一个直译的名字问题
public boolean equals(Object otherObject)
{
//2.检查this与otherObject的对象是否相等(==用来判断指针值,或者判断null值相等)
if(this == otherObject)
return true;
//3.检查otherObject是否为null,用于实现对当前类非null时对null的独特判断方式
if(otherObject == null)
return false;
//4.比较this与otherObject是否为同一个类,实现对称性
if(this.getClass() != otherObject.getClass())
return false;
//这里书中提到如果子类都具有统一的语义则可以使用instanceof操作符,不过既然不知道语义是否被修改,那么一直使用getClass它不香吗
//5.将otherObject转换为与this相应的类类型变量,并判断两者中所有域是否相等
//(其中基本类型采用==操作符比较,对象采用equals进行比较)
Employee other = (Employee)otherObject;
return name.equals(other.name) && salary == other.salary && hireDay.equals(other.hireDay);
}
}
散列码是用来表示当前对象独特性的一个整型值(所以总是要和equals一致,两个都是表示一个对象的独特性的),与其相关有几点如下:
这个函数说穿了就是把对应类中的所有参数名字与值全部变成String类型展示出来,换句话说就是便于获取当前类中的所有参数信息。
首先讲了Java中最棒的数组变量大小设计,这相对于C++来说这简直是太棒了!
int size = ...;
Employee[] staff = new Employee[size];
然后讲了Java的动态数组ArrayList,并提到了两个方法:
这里还提到了ArrayList没有重载[]运算符(哦我的上帝!这可太蠢了),同时表示将ArrayList类进行=操作符赋值时会导致两个ArrayList使用的都是同一个内存的ArrayList(毕竟指针传递,问题不大)
主要讲了ArrayList的几个关键函数,从这几个关键函数我看出了这个动态数组设计的还是有点蠢的(index必须保证在size() - 1到0之间):
Java的动态数组看来和C++一样,理论上都是适合读取数据,不适合插入与删除数据。不过不了解Java的链表的底层数据结构不清楚,反正std::list就是一场灾难。
这里讲了一个update()函数,没太能搞明白想表达意思,应该是说在类里面自定义一个update函数便于操作某些现有数组?
这里涉及到Java的特色操作了,即每个基本类型都对应一个特有的类,这些类往往被称为包装器,这些包装器都是final类型的类,即无法被继承。这些包装器的名字都相当典型:Integer、Long、Float、Double、Short、Byte、Character、Void和Boolean,其中前六个都是派生于公共的超类Number。然后这些包装类的值是不可变动的,一旦构造则无法被修改。
Java通过类似Object … args这样的形参描述表达可以接受任意数量的Object 对象,这种情况类似于传递了一个Object[]数组。(说实话我不太喜欢这个功能,我个人认为必须保证形参的数据结构确定性,不然编码过程会很头疼)
Java的枚举类很常规,都是public enum Size{ SMALL, LARGE, …}这样的表达方式。但是很骚气的是他可以在其中添加构造器、方法和域,通俗的理解来说就是枚举Size中的每个单独枚举比如SMALL以及LARGE这样的都是Size枚举的一个实例,然后通过定义Size的内部参数以及构造器等方式可以为SMALL以及LARGE这样的实例进行初始化,从而在对应不同的枚举时调用方法的结果都可以有所不同。这里记录一下:
public enum Size
{
SMALL("S"), MEDIUM("M"), LARGE("L"), EXTRA_LARGE("XL");
private String abbreviation;
private Size(String abbbreviation) {this.abbbreviation = abbbreviation;}
public String getAbbbreviation( return abbbreviation;}
}
说实话我现阶段真的看不太懂反射,这里明确表示能够分析类能力的程序称之为反射(reflective),这里简单记录下书中描述的反射作用:
保存对象运行时类型标识信息的类被称为Class,这个类实际上是一个泛型类,就像template< typename >这样的存在。其常用的方法是getName(),具体表现为【包名+类名】。
两种异常类型:未检查异常与已检查异常,检测异常则为经典的try catch方式。
从这里开始打算把反射先放一放,暂时不太能具体理解这种方法的使用状态,简单记录下java.lang.reflect包中的三个类:
if(x is of type1)
action1(x);
else if(x is of type2)
action2(x);
//将根据type的不同操作封装在action中,从而直接调用action即可:
x.action();
后记:这一章主要讲了Java的类、继承和多态,也就是相关类设计者的基础知识,整体来看其实与C++的区别并不大,有些地方的改进很有特色(比如动态数组,类中的main函数等等),但是有的地方就改进的稀烂(比如ArrayList的那几个函数),但是总体而言还是感觉Java的编写方式其实更好操作一点。