1. 抽象类 abstract class
抽象方法,只有行为的概念,没有具体的行为实现 1) 使用:abstract 关键字修饰,并且没有方法体 2) 包含抽象方法的类,就一定是抽象类 使用: abstract 关键字修饰,包含抽象方法 3) 抽象类不能直接创建实例。可以定义引用变量 Shape shape = new Shape() 错
Shape shape = new Circle() 对
4) 抽象类只能被继承,一个具体类继承一个抽象类,必须实现所有抽象方法
5) 抽象方法和抽象类是非常适合作为系统的分析和设计的工具
我们使用标准写法重构设计图形(Shape)类的案例,如下图所示
/**
* 包含抽象方法的类一定是抽象类
* 普通类,是具体类,是具体概念,如,,圆,单选题
* 抽象类:不具体,表达抽象概念,如:圆形,考题
*/
public abstract class Shape{
protected Point location;
/*
* 抽象方法,图像可以计算面积
* 具体计算过程不清楚。*/
public abstract double area();
public boolean contains (Point p){
return contains(p.x,p.y);
}
public abstract boolean contains(int x,int y);
}
/**
*圆是具体类 ,继承图形必须实现图形中的所有抽象方法
*图形的抽象方法是子类的约定,约定子类具有一致的公共外观
*(一定包含area()和contains(int x,int y)方法)
* @param args
*/
public class Circle extends Shape{
private int r;
public Circle(int x,int y,int r){
location = new Point(x,y);
this.r = r;
}
//实现shape中约定的方法
public double area() {
// TODO Auto-generated method stub
return Math.PI*r*r;
}
//实现shape中约定的方法
public boolean contains(int x, int y) {
return this.location.distance(x,y)<=r;
}
}
public class ShapeDemo {
public static void main(String[] args) {
//代词可以是抽象的,东西必须是具体的
Shape s = new Circle(5,6,4);
Point p = new Point(7,8);
System.out.println(s.area());
System.out.println(s.contains(p));
}
}
2. 接口 interface
我们使用抽象方法和抽象类作为系统的分析和设计的工具,用来实现客户关系管理业务的架构,
public class abstract CRMSystem
{ public abstract Client add(Client newGuy); //添加用户方法
public abstract Event add(Event e, Client guy); //重载添加事件、用户方法
public abstract Event[] todayEvents(); //今日事件方法 }
如上代码中没有方法具体实现的情况,我们就可以使用接口(interface),相当于c++中的虚类
public interface CRMSystem{
Client add(Client newGuy);
Event add(Event e, Client guy);
Event[] todayEvents(); }
接口:全部的方法都是抽象方法,全部的属性都是常量
1) 接口是特殊的抽象类
2) 接口用来表示纯抽象概念,没有任何具体的方法和属性
3) 接口丌能实例化,可以定义变量
Shape s = new Shape(); 错 Shape s = new Circle(); 对
4) 接口变量可以引用具体实现类的实例
5) 接口只能被实现(继承),一个具体类实现接口,必须使用全部的抽象方法
6) 接口之间可以继承(implements)
7) 一个具体类可以实现多个接口,实现多继承现象
表示:一个概念即是XXX也是XXX
8) 接口中的属性,默认是常量 public static final
9) 接中的方法一定是public abstract的(默认,可以丌写)
10) 实现一个接口,使用关键字implements,实现实际上是一种继承关系
接口和实现类是父子类型的关系
案例如下所示
Car.java
/**
* 小汽车概念
* 表示所有的汽车都能跑,都能停*/
public interface Car{
void run();
void stop();
}
Product.java
/**
* 产品
* 表示:产品*/
public interface Product{
double getPrice();
}
QQ.java
public class QQ implements Car,Product{
public double getPrice() {
return 3000;
}
public void run() {
System.out.println("run");
}
public void stop() {
System.out.println("stop");
}
}
QQDemo.java
public class QQDemo{
public void main (String [] args){
QQ qq = new QQ()//创建一辆QQ车
Product p = qq; //qq车是一个Product
System.out.println(
p.getPrice());//输出这个Product的价格
Car car = qq;//QQ是一个Car
car.run();
car.stop();
Car c = (Car)p;这个Product 是car可以强转
c.run();
c.stop();
}
}
3. Object类
Object类是一切类的父类,Java 所有类都默认继承Object
1) 所有类都继承了Object 的属性和方法
如: toString()、hashCode()、equals() 等
2) toString()方法,经常由系统默认调用,是活劢当前对象的文本描述
Object默认返回值: 全限定名为@hashCode
建议覆盖为:当前对象的文本描述
Java 类默认继承于Object,用一句话形容就是:“啥都是东西”。Java类继承了Object的所有属性和方法,如: toString(), hashCode(),equals()
1) toString() 方法
经常由系统默认调用,是活劢当前对象的文本描述
Object默认返回值: 全限定名@hashCode
建议覆盖为: 当前对象的文本描述
2) equals()方法
用来比较两个对象是否相等的方法
比较对象分为两种:“引用相等”与“对象相等”
比较引用值是否相等: “==”
比较对象的内容是否相等:xxx.equals()方法
equals在Object类中声明,默认的比较规则是:比较引用
建议覆盖,实现对象的比较(比较对象的状态,就是比较对象的数据
自反性:对于任何非空引用值 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) 始终返回 true 戒始终返回 false,前提是对象上 equals 比较中所用的信息没有被修改。
对于任何非空引用值 x,x.equals(null) 都应返回false。
3) hashCode() 方法
hashCode()方法要不equals方法一同覆盖(Sun公司规定)
当两个对象equals比较为true时,应具有相同的hashCode()值
当两个对象equals比较为false时,应具有丌相同的hashCode()值
hashCode() 值要稳定(一致性),一个对象创建以后就丌应该再变化
默认的hashCode()值是当前堆对象地址转换的一个整数,这个整数不是内存地址!
一般使用对象的OID值作为hashCode的值
OID是对象的唯一编号,在项目中一般采用数据库生成OID,也就是数据库中的“主键”。
equals()方法是模式化写法,在今后写程序过程中模仿照抄即可
public boolean equals(Object obj){
if(obj==null)//与null比较返回false
return false;
if(this==obj)//obj对象就是当前(this)对象,返回true
return true;
if(obj instanceof QQ){//检查obj引用的对象是否是QQ类型
Card other = (Card)obj;//引用类型转换,方便访问属性
return this.price == other.price &&
this.speed==other.speed;
}
return false;//类型不一致返回false
}