抽象类
java中可以定义一些不含方法体的方法,它的方法体的实现交给该类的子类根据自己的情况去实现,这样的方法就是抽象方法,包含抽象方法的类就叫抽象类。
-
抽象类必须用abstract关键字来修饰;抽象方法也必须用abstract来修饰。
-
抽象类不能被实例化,也就是不能用new关键字去产生对象。
-
抽象方法只需声明,而不需实现。
-
含有抽象方法的类必须被声明为抽象类,抽象类的子类必须覆盖所有的抽象方法后才能被实例化,否则这个子类还是个抽象类,而且必须用abstract修饰类名
接口(interface)
如果一个抽象类中的所有方法都是抽象的,我们就可以将这个类用另外一种方式来定义,也就是接口定义。接口是抽象方法和常量值的定义的集合,从本质上讲,接口是一种特殊的抽象类,这种抽象类中只包含常量和方法的定义,而没有变量和方法的实现。
-
接口中的成员都是public访问类型的。接口里的变量默认是用public static final标识的。
-
我们可以定义一个新的接口用extends关键字去继承一个已有的接口
-
我们也可以定义一个类用implements关键字去实现一个接口中的所有方法,我们还可以去定义一个抽象类用implements关键字去实现一个接口中定义的部分方法。
-
一个类可以继承一个父类的同时,实现一个或多个接口,extends关键字必须位于implemnets关键字之前。
示例如下:
1.
interface Animal extends Runner //一个接口继承另一个接口
{
int ID=1; // 因为默认为public static final,相当于常量,所以变量名大写
void breathe();
}
interface Runner
{
void run();
}
2.
class Fish implements Animal //一个类实现一个接口的所有方法
{
public void run()
{
System.out.println("鱼的游泳代码");
}
public void breathe()
{
System.out.println("鱼的呼吸代码");
}
public static void main()
{
Fish f=new Fish();
int y=0;
y=Runner.ID; //因为是static 所以可以直接引用
y=Fish.ID; //从Fish从Runner继承来的
y=f.ID;
f.ID=5; //错误,因为ID 是final型的
}
}
3.
abstract class LandAnimal implements Animal //一个抽象类实现接口中的
{ //部分方法
public void breathe()
{
System.out.println("陆生生物呼吸的代码");
}
}
4. class Student
extends Person implements Animal //一个类继承一个父类,
{ //并且实现一个接口的
public void run() //所有方法
{
System.out.println("学生奔跑的代码");
}
public void breathe()
{
System.out.println("学生呼吸的代码");
}
}
class Person
{
String name="unknown";
}
5. class Bird
implements Runner,Flyer //一个类实例多个接口的所有方法
{
public void run(){}
public void fly(){}
}
interface Flyer
{
void fly();
}
定义接口类用“interface 类名”的方式,如:
interface A
{
String name=”戴振良”; //接口中的成员变量系统会默认加上“public static final”修饰符
int func1(int x); //接口类中的方法不需要用abstract修饰
void func2();
}
//接口的应用,该程序模拟主板插声卡与插网卡的应用
interface PCI //定义PCI接口的规范
{
void start();
void stop();
}
class soundCard implements PCI //按照PCI接口的规范定义声卡的功能
{
public void start()
{
System.out.println("嘟嘟嘟...");
}
public void stop()
{
System.out.println("停止声音");
}
}
class networkCard implements PCI //按照PCI接口的规范定义网卡的功能
{
public void start()
{
System.out.println("发送数据信息....");
}
public void stop()
{
System.out.println("停止发送数据");
}
}
class mainbord //按照PCI接口的规范定义主板PCI卡槽的功能
{
public void usePCICard(PCI pci)
{
pci.start();
pci.stop();
}
}
class assembler //定义一个电脑组装者
{
public static void main(String[] args)
{
mainbord mb=new mainbord(); //组装者买了一块主板
soundCard sc=new soundCard(); //组装者买了一块声卡
networkCard nc=new networkCard(); //组装者买了一块网卡
mb.usePCICard(sc); //把声卡插到主板上,拥有了声音的功能
mb.usePCICard(nc); //把网卡插到主板上,拥有了发送数据的功能
mb.usePCICard(new PCI() //匿名内置类的使用非常之多,要熟练掌握。这里定义了
{ //了一个匿名内置类,相当于厂商制作了一个PCI规范的卡,用于测试主板
public void start()
{
System.out.println("测试主板……");
}
public void stop()
{
System.out.println("停止测试");
}
}
);
}
}
//上面的匿名内置类相当于:
/*class A implements PCI
{
public void start()
{
System.out.println("Test Start");
}
public void stop()
{
System.out.println("Test Stop");
}
}
mb.usePCICard(new A()); */
对象的类型转换
-
子类对象可以自动转换成父类
-
父类转换成子类必须使用强制转换。
-
instanceof 操作符可以用它来判断一个实例对象是否属于一个类。Object类及equals方法
假如B继承于A:
A a=new B( );//这是可以的,但使用a实例时只能使用A类中有的方法或B类的重写方法
B b=(B) a;//必须这样做才能把实例a赋值给子类b
if(a instanceof B)//判断实例a是否是B类的类型的实例 -
如果在声明一个类时没有写明继承哪一个类的话,则默认继承了Object类,如声明“class a”等“class a extends Object”
-
object类中有一个equals方法,用于比较两个对象是否相等,即比较两个对象中的属性值是否都相等。 注意在使用时必须重写该方法,否则就会一直都是返回false,重写代码如下:
假设有个Student类,类中有一个name成员与age成员:
public boolean equals (Object obj)
{
Student st=null;
if(obj instanceof Student)
{
st=(Student)obj;
if(st.name==name&&st.age=age)
return true;
else
return false;
}
else
return false;
} -
equals的用法:st1.equals(st2);
面向对象的多态性
-
应用程序不必为每一个派生类(子类)编写功能调用,只需要对抽象基类进行处理即可。这一招叫“以不变应万变”,可以大大提高程序的可复用性。
-
派生类的功能可以被基类的引用变量引用,这叫向后兼容,可以提高程序的可扩充性和可维护性。以前写的程序可以被后来程序调用不足为奇,现在写的程序(如callA方法)能调用以后写的程序(以后编写的一个类A的子类,如类D)就了不起了。
匿名内部类
abstract class A
{
abstract public void fun1();
}
class Outer
{
public static void main(String [] args)
{
new Outer().callInner(new A()
{
public void fun1()
{
System.out.println("implement for fun1");
}
});
}
public void callInner(A a)
{
a.fun1();
}
}
//匿名内置类的使用非常多,要熟练掌握