发表于: 2017-10-31 01:39:11
1 833
今天完成的事情:
现在大概了解RMI是干什么的了 在网上查了很多只是有简单的demo
然后也看了前面师兄的小课堂 感觉收获不大
现在的问题是我知道这个东西一些皮毛的东西 但是不会再自己的代码里面用到他
我不知道怎么把service分离出来
然后还有一个web客户端我不知道写在哪 感觉脑子一片混乱
今天照常继续看了java基础
继承
类、超类和子类
is-a”关系是继承的一个明显特征,关键字extends表示继承。例如:
class Manager extends Employee{
.... // Manager类继承了Employee类
}
关键字extends
表明正在构造的新类派生于一个已存在的类。已存在的类被称为超类(superclass)
、基类(base class)
或父类(parent class)
;新类被称为子类(subclass)
、派生类(derived class)
或孩子类(child class)
。超类和子类是Java程序员最常用的两个术语。
在通过扩展超类定义子类的时候,仅需要指出子类与超类的不同之处。因此在设计类的时候,应该将通用的方法放在超类中,而将具有特殊用途的方法放在子类中。
若超类中的某些方法对于子类中并不适用,就需要提供一个新的方法来覆盖(override)
超类中的这个方法。但如果在这个新的方法中需要调用超类中的同名方法的时候,可以用super
来调用,例如:
public double getSalary(){
double baseSalary = super.getSalary();
return baseSalary + bonus;
}
在子类中可以增加域、增加方法或覆盖超类的方法,然而绝不能删除继承的任何域和方法。
super在构造器中用来调用超类的构造器,例如:
public Manager( String n, double s, int year ){
super( n, s, year );
bonus = 0;
}
如果子类的构造器没有显式地调用超类的构造器,则将自动地调用超类默认的构造器。如果超类没有不带参数的构造器,并且在子类的构造器中又没有显式地调用超类的其他构造器,则Java编译器将报告错误。
继承并不仅限于一个层次,由一个公共超类派生出来的所有类的集合被称为继承层次(inheritance hierarchy)
。在继承层次中,从某个特定的类到其祖先的路径被称为该类的继承链(inheritance chain)
。
通常,一个祖先类可以拥有多个子孙继承链。Java不支持多继承。
有一个用来判断是否应该设计为继承关系的简单规则,这就是is-a
规则,它表明子类的每个对象也是超类的对象。
is-a
规则的另一种表述方式是置换法则。它表明程序中出现超类对象的任何地方都可以用子类对象置换。
在Java程序设计语言中,对象变量是多态的。一个超类变量既可以引用一个超类对象,也可以引用一个此超类的任何一个子类的对象。然而,不能将一个超类的引用赋给子类变量。
弄清调用对象方法的执行过程十分重要。下面是调用过程的描述:
编译器查看对象的声明类型和方法名。假设调用x.f(param)
,且隐式参数x
声明为C类的对象。编译器将会一一列举所有C
类中名为f
的方法和其他超类中访问属性为public
且名为f
的方法。
至此,编译器已获得所有可能被调用的候选方法。
接下来,编译器查看调用方法时提供的参数类型。如果在所有名为f
的方法中存在一个与提供的参数类型完全匹配,就选择这个方法。这个过程被称为重载解析(overloading resolution)
。如果编译器没有找到与参数类型匹配的方法,或者发现经过类型转换后有多个方法与之匹配,就会报告一个错误。
至此,编译器已获得需要调用的方法名字和参数类型。
如果是private
方法、static
方法、final
方法或者构造器,那么编译器可以准确地知道应该调用哪个方法,这种调用方式称为静态绑定(static binding)。与此对应的是,调用的方法依赖于隐式参数的实际类型,并且在运行时实现动态绑定。
当程序运行,并且采用动态绑定调用方法时,虚拟机一定调用与x
所引用对象的实际类型最合适的那个类的方法。
每次调用方法都要进行搜索,时间开销相当大。因此,虚拟机预先为每个类创建了一个方法表(method table),与C++中的VTABLE类似,其中列出了所有方法的签名和实际调用的方法。实际调用时查找此表即可。
动态绑定有一个非常重要的特性:无需对现存的代码进行修改,就可以对程序进行扩展。
不允许扩展的类被称为final
类。如果在定义类的时候使用了final
修饰符就表明这个类是final类。可以阻止人们定义其子类,如:
final class Executive extends Manager{...}
类中的方法也可以被声明为final如果这样做,子类就不能覆盖这个方法(final
类中的所有方法自动成为final
方法)。如:public final int getValue()
将方法或类声明为final的意义在于:确保它们不会在子类中改变语义。
对象引用的转换语法与数值表达式的类型转换类似,仅需要用一对圆括号将目标类名括起来,并放置在需要转换的对象引用之前就可以了。
在进行类型转换之前,先查看以下是否能够成功地转换。可以简单地使用instanceof运算符实现,如:
if( staff[1] instanceof Manager){
boss = (Manager) staff[1];
......
}
综上所述,有两个原则:
- 只能在继承层次内进行类型转换。
- 在超类传唤成子类之前,应该使用
instanceof
检查。
一般情况下,应该尽量少用类型转换和instanceof
运算符。
如果自下而上仰视类的继承层次结构,位于上层的类更具有通用性,甚至可能更加抽象。从某种角度看,祖先类更加通用,人们只将它作为派生其他类的基类,而不作为想使用的特定实例类。
使用abstract
关键字来声明抽象类。
public abstract String getDescription();
// no implementation required
为了提高程序的清晰读,包含一个或多个抽象方法的类本身必须被声明为抽象的。除了抽象方法之外,抽象类还可以包含具体数据和具体方法。
抽象方法充当占位的角色,它们的具体实现在子类中。扩展抽象类可以有两种选择。一种是在子类中定义部分抽象方法或抽象方法也不定义,这样就必须将子类也标记为抽象类;另一种是定义全部的抽象方法,这样一来,子类就不是抽象的了。
类即使不含抽象方法,也可以将类声明为抽象类。
抽象类不能被实例化,即不能创建抽象类的对象。但是可以定义一个抽象类的对象变量,但是它只能引用非抽象子类的对象。
- 仅对本类可见──private。
- 对所有类可见──public。
- 对本包和所有子类可见──protected。
- 对本包可见──默认。
Java中的protected概念要比C++中的安全性差。
Object 所有类的超类
Object
类是Java中所有类的最终祖先,在Java中每个类都是由它扩展而来的。如果没有明确地指出超类,Object
就被认为是这个类的超类。
可以使用Object
类型的变量引用任何类型的对象。当然,Object
类型的变量只能用于作为各种值的通用持有者。要想对其中的内容进行具体的操作,还需要清楚对象的原始类型,并进行相应的类型转换。
在Java中,只有基本类型(primitive types)
不是对象。
Object
类中的equals
方法用于检测一个对象是否等于另一个对象。在Object
类中,这个方法将判断两个对象是否具有相同的引用。
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)
返回true
,x.equals(z)
也应该返回true
。 - 一致性:如果
x
和y
引用的对象没有发生变化,反复调用x.equals(y)
应该返回同样的结果。 - 对于任意非空引用
x
,x.equals(null)
应该返回false
。
可以从两个截然不同的情况看待getClass的使用:
- 如果子类能够拥有子集的相等概念,则对称性需求将强制采用getClass进行检测。
- 如果由超类决定相等的概念,那么就可以使用instanceof进行检测,这样就可以在不同子类对象之间进行相等的比较。
下面给出编写一个完美的equals方法的建议:
- 显式参数命名为
otherObject
,稍后需要将它转换称另一个叫做other
的变量。 - 检测
this
与otherObject
是否引用同一个对象:if( this == otherObject ) return true;
- 检测
otherObject
是否为null
,如果为null
,返回false
。if( otherObject == null ) return false;
- 比较
this
与otherObject
是否属于同一个类。 - 如果
equals
语义在每个子类中有所改变,就使用getClass
检测:if (getClass() != otherObject.getClass()) return false;
- 如果所有的子类拥有统一的语义,就使用
instanceof
检测:if( ! ( otherObject instanceof ClassName )) return false;
- 将
otherObject
转换相应的类型变量:ClassName other = ( ClassName )otherObject;
现在开始对所有需要比较的域进行比较。使用 ==
比较基本类型域,使用equals
比较对象域。如果所有都匹配,就返回true
,否则返回false
return field1 == other.field1
&& field2.equals(other.field2)
&& ...;
如果在子类中重新定义equals
,就要在其中包含调用super.equals(other)
。
散列码(hash code)
是由对象导出的一个整型值,是没有规律的。可以用做来判断对象是否相等。
java.lang.Object
int hashCode()
- 返回对象的散列码。散列码可以是任意的整数,包括正数或负数。两个相等的对象要求返回相等的散列码。
Class getClass()
- 返回包含对象信息的类对象。Java提供了类运行时的描述,被封装在Class类中。
boolean equals( Object otherObject )
- 比较两个对象是否相等,如果两个对象指向同一块存储区域,方法放回true;否则方法返回false。在自定义类中,应该覆盖这个方法。
String toString()
- 返回描述该对象值的字符串。在自定义类中,应该覆盖这个方法。
Object clone()
- 创建一个对象的副本。Java运行时系统将为新实例分配存储空间,并将当前的对象复制到这块存储区域中。
java.lang.Class
String getName()
- 返回这个类的名字。
Class getSuperclass()
- 以Class对象的形式返回这个类的超类信息。
在Object
中还有一个重要的方法,就是toString
方法,它用于返回表示对象值的字符串。绝大多数的toString
方法都遵循这样的格式:类的名字,随后是一对方括号括起来的域值。
如果x
是任意一个对象,并调用System.out.println(x)
; 就会直接调用x.toString()
,并打印输出得到的字符串。
这些大概就我看的东西的梗概
明天的计划:继续学习基础部分 然后争取跟师兄沟通下 把任务8指导下 毕竟不是什么很抽象很难的东西快点做完补基础
遇到的问题:真的是不知道该怎么操作。。 这个很烦恼
收获:java基础部分 今天对于RMI的学习感觉没有多大长进
效率上的话肯定是比前段日子要好得多 没怎么分心
任务进度:任务8步骤1
任务开始时间:2017-10-28
预计结束时间:2017-11-5
禅道:http://task.ptteng.com/zentao/task-view-10472.html
评论