1.toString方法
- object中定义有toString()方法,其返回值是string类型,它描述的是当前对象的有关信息。
- 在进行string与其他类型数据的连接操作时(如system.out.println(“info”+person)),将自动调用该对象的toString()方法。
- 可以根据用户需要重写toString()方法。
2.equals方法
- public boolean equals(object obj)方法提供定义对象是否“相等”的逻辑。
- object的equals()方法定义为:x.equals(y) 当x和y是同一个对象的引用时,返回true,否则返回false。
- j2se提供的一些类,如String Date等,重写object的equals()方法,调用这些类的equals()方法,x.equals(y)方法,当x和y所引用的对象是同一类对象且属性内容相等时(并不一定是相同对象),返回true,否则返回false。
- 可以根据用户需要在自定义类型中重写equals()方法。
- 注意:当此方法被重写时,通常有必要重写 hashCode 方法,以维护 hashCode 方法的常规协定,该协定声明相等对象必须具有相等的哈希码。
3.对象转型(casting)
一个基类的引用类型变量可以“指向”其子类的对象。(父类引用指向子类对象)——它所看到的只是作为父类的那部分所拥有的那些属性和方法。
一个基类的引用不可以访问其子类对象新增加的成员(属性和方法)。
可以使用 引用变量 instanceof 类名 来判断该引用型变量所“指向”的对象是否是该类或该类的子类。
子类的对象可以当作基类的对象来使用称作向上转型,反之称为向下转型。
对象转型可以增加程序的可扩展性。
4.多态(动态绑定、迟绑定)——核心机制
- 动态绑定是指在执行期间(而非编译期)判断所引用对象的实际类型,根据其实际类型调用其相应的方法。
- 多态的三个必要条件:
- 要有继承
- 要有重写
- 类引用指向子类对象(实际中new的是哪一个子类对象就调用哪一个子类对象的方法)
- 多态性通过覆盖父类的方法来实现,在运行时根据传递对象的引用来调用相应的方法。
- 多态就是:传递子类的引用时,子类有的方法就调用子类的对象,子类没有就调用父类的对象。
- 多态机制是面向对象的核心机制,增强程序的可扩展性。它是根据实际的类型去调用相应的方法。
- 继承是子类使用父类的方法,而多态则是父类使用子类的方法。其技术上的区别是绑定时期,晚期绑定一定是多态。
- 多态性不仅包括方法多态性(重载),还包含一种对象多态性的概念,即子类和父类对象的相互转化关系。
- 向上转型:父类 父类对象=子类实例 (自动完成)
- 向下转型:子类 子类对象=(子类)父类实例(强制完成)
- 对象多态性最核心的部分就是方法的重写与继承关系,只要有继承关系,只要有重写过的方法,则子类向父类转型时,肯定是调用被子类重写过的方法(核心)。
- 多态性是指在继承层次或者接口与实现类层次上,如果子类覆盖了父类的方法,或者说实现类实现了接口 定义的方法,那么可以通过一般化的用父类或者接口来调用该方法,JVM在运行期能够根据实际传递的子 类对象引用,来调用相应的方法,产生正确的行为。达到“同一函数,不同行为”的效果。java的多态性是通过动态绑定实现的。
- 首先是多态性的前提:
- 在继承层次或者接口与实现类层次上才有多态性;
- 子类覆盖了父类的方法,或者实现类实现了接口定义的方法,才有多态性;
- 其次是多态性的表现:
可以通过一般化的用父类或者接口来调用某一方法,JVM在运行期能够根据实际传递的子类对象引用,来调用相应的方法,从而产生正确的行为。 - 最后是多态性的实现原理:
java多态性是通过函数的动态绑定机制实现的
5.抽象类
- 用abstract修饰一个类时,该类是一个抽象类。用abstract修饰一个方法时,该方法是一个抽象方法(相当于C++中的纯虚函数)。
- 含有抽象方法的类必须为抽象类,抽象类不一定要包含抽象方法。
- 抽象类必须被继承,抽象方法必须被重写(由子类去实现)。
- 抽象类不能被实例化。但是利用多态可以通过子类实例化。
- 抽象方法只需声明,不需实现。
- 抽象类可以包含具体数据或具体方法。
- 抽象类能否使用final声明呢?
a) 抽象类必须被子类继承
b) 被final声明的类不能有子类 - 抽象类中能不能存在构造方法?
a) 允许有构造方法
b) 但是不能直接调用,是要交给子类调用的,子类对象的实例化中永远是先调用父类中的构造方法
c) 由此而知,抽象类只不过是比普通类多了一个抽象方法而已 - 抽象类中的属性如果要初始化,则还是要依赖于构造方法
- 抽象类实际上可以作为模板存在。
6. final关键字
- final变量(成员变量与局部变量)的值不能被改变。(局部变量作为形参时,方法内部是不允许改变的)
- final的方法不能被重写。
- final的类不能被继承。
7.接口
- 多个无关的类可以实现一个接口
- 一个类(或者抽象类)可以实现多个无关的接口,但是一个接口不能继承一个抽象类
- 一个接口可以同时继承多个接口
- 与继承关系类似,接口与实现类之间存在多态性(实现接口的方法就是多态)
- 接口是常量值和抽象方法的定义的集合
- 从本质上讲,接口是一种特殊的抽象类,这种抽象类中只包含常量和方法的定义,而没有变量和方法的实现
- 接口不是类,不能用new运算符实例化一个接口,但是也是可以利用多态性通过其实现类实例化。
- 虽然不能构造接口对象,却能声明接口变量
- 接口变量必须引用实现了接口的类对象
- 可以使用instanceof检查一个对象是否实现了某个接口
- 接口可以扩展。即可以interface1 extends interface2。也可以添加新的属性和方法
- 接口中的方法和域被自动设置为public static final(C++中多继承中,如果它的多个父类之间有相同的成员变量时,运行起来会相当得麻烦,并且会出现很多问题。为了修正这个缺陷,java中把成员变量修饰为static使这个变量只属于这个类(因为在多继承中,子类对象包含多个父类对象,而多个父类对象之间是有可能出现相同的成员变量的,所以用static修饰,它就不属于专门的对象),用final修饰使这个变量不被改变)
- 接口中只能定义抽象方法,而这些方法默认为public的,而且也只能是public的。
- 接口可以多重实现(多继承)。
- 多继承中,子类对象是包含多个父类对象的。
- 接口实际上是作为标准存在的。
8. 接口和抽象类
8.1 适配器设计模式
a) 正常情况下一个接口的子类要实现全部的抽象方法
b) 但是现在希望可以根据自己的需求来选择性的重写,应该怎么是实现呢?
c) 就用一个类先将接口实现了,但是所有的方法都是空实现,之后再继承此类
d) 这个类必须是抽象类,因为抽象类也不能直接使用。此抽象类就相当于适配器。
8.2 工厂设计模式
a) 现在有如下一道程序:
interface Fruit{
public void eat() ;
}
class Apple implements Fruit{
public void eat(){
System.out.println("吃苹果。。。") ;
}
};
class Orange implements Fruit{
public void eat(){
System.out.println("吃橘子。。。") ;
}
};
class Factory{ // 工厂类
public static Fruit getFruit(String className){
Fruit f = null ;
if("apple".equals(className)){
f = new Apple() ;
}
if("orange".equals(className)){
f = new Orange() ;
}
return f ;
}
};
public class InterDemo{
public static void main(String args[]){
Fruit f = Factory.getFruit(args[0]) ;
if(f!=null){
f.eat() ;
}
}
}
所有的接口的实例化对象都是通过工厂类取得的,那么客户端调用的时候就根据传入的名称不同,完成的功能也不同。是为了解开接口和子类之间的耦合性。
8.3 代理设计模式
interface Give{
public void giveMoney() ;
}
class RealGive implements Give{
public void giveMoney(){
System.out.println("把钱还给我。。。。。") ;
}
};
class ProxyGive implements Give{ // 代理公司
private Give give = null ;
public ProxyGive(Give give){
this.give = give ;
}
public void before(){
System.out.println("准备:小刀、绳索、钢筋、钢据、手枪、毒品") ;
}
public void giveMoney(){
this.before() ;
this.give.giveMoney() ; // 代表真正的讨债者完成讨债的操作
this.after() ;
}
public void after(){
System.out.println("销毁所有罪证") ;
}
};
public class ProxyDemo{
public static void main(String args[]){
Give give = new ProxyGive(new RealGive()) ;
give.giveMoney() ;
}
};