继承(extends),多态,抽象类与接口
一,继承
1,Java语言每个类只能继承一个父类
2,父类 和普通类写法相同
public class 父类类名{
}
3,子类
public class 子类类型 extends 父类类名{
}
例题7.1:
例题7.2:
4,所有类的构造方法第一行都有一个隐藏的" super();"
作用是在执行该构造方法之前调用其父类的构造方法。
二,ob ject 类
1,getClass()的方法:是Object类定义的方法,它会返回对象执行时的Class实例
getClass().getname();
2,toString()方法:将一个对象返回为字符串形式,它会返回一个String实例。
3,方法的重写:
返回参数相同 方法名相同 传入参数相同 方法体
例题7.3:
4,equals方法:有两种比较对象的方式,分别为“==”运算符与equals()方法。
例题7.4代码与结果:
三,对象类型的转换
1,向上转型:子类对象赋值给父类引用 (自动转换)
animal a = new dog();
2,向下转型:父类对象赋值给子类引用(需要进行强制转换)
dog a = (dog) new animal();
例题7.6:
五,方法的重载
重写:(子类—父类) 参数相同 方法名相同 传入参数相同 只有方法体不同
重载:方法名相同,参数不同
例题7.8:
例题7.9:
六,final关键字
1,final修饰变量----不可以被修改(常量)
例题7.10
2,final修饰方法-----不可以被重写
例题7.11
3,final修饰类-----不可以被继承
七,使用instanceof关键字判断对象类型
语法格式:
1,对象名 instanceof 类名
判断对象是否属于该类或子类
例题7.7
八,多态
例题7.12
7.3.1 方法的重载
方法的重载意义:在同一个类中允许同时存在一个以上的同名方法,只要这些方法的参数个数或类型不同即可。
重载与重写是两个完全不同的概念,重载主要用于一个类内实现若干重载的方法。这些方法的名称相同而参数形势不同;而重写主要用于子类继承父类时,重新实现父类中的非私有方法。
7.3.2 向上转型
把子类对象赋值给父类类型的变量,这种技术被称为“向上转型”。
在执行向上转型操作时,父类的对象无法调用子类独有的属性或者方法。
class Quadrangle { //四边形类
public static void draw( Quadrangle q) { //四边形类中的方法
//SomeSentence
}
}
public class Parallelogram extends Quadrangle { //平行四边形类,继承了四边形类
public class void main(String args[]) { //实例化平行四边形类对象引用
Parallelogram p = new Parallelogram();//调用父类方法
draw(p);
}
}
7.3.3 向下转型
通过向上转型可以推理出向下转型是将较抽象的类转换为较具体的类。
向下转型通常会出现问题:将父类对象直接赋予子类,会发生编译器错误,因为父类对象不一定是子类的实例。
越是具体的对象具有的特性越多,越抽象的对象具有的特性越少。
class Restaurant {
public static void draw( Restaurant q) {
//SomeSentence
}
}
public class parallelogram extends Restaurant {
public static void main(String[] args[]) {
draw(new parallelogram () );
//将平行四边形类对象看作是四边形对象,称为向上转型操作
Restaurant q = new parallelogram();
parallelogram p=q; //将父类对象赋予子类对象
//修改:parallelogram q= (parallelogram) q;
}
}
7.3.4 instanceof 关键字
myobject instanceof ExampleClass
class Quadrangle { public static void draw(Quadrangle q) { //SomeSentence } } class Square extends Quadrangle { //SomeSentence class Anything { //SomeSentence public class parallelogram extends Quadrangle { public static void main(String[] args[]) { Quadrangle q = new Quadrangle //实例化父类对象 //判断父类对象是否为Parallelogram子类的一个实例 if (q instanceof Parallelogram) { Parallelogram p = (Parallelogram) q; //进行向下转型操作 //判断父类对象是否为Parallelogram子类的一个实例 if (q instanceof Square) { Square s = (Sauare) q; //进行向下转型操作 } //由于q对象不为Aaything类的对象,所以这条语句是错误的 //System.out.println(q instanceof Anything); } }
注意:instanceof是Java语言的关键字,在Java中的关键字都为小写。
7.4 抽象类与接口
7.4.1 抽象类与抽象方法
在解决实际问题时,一般将父类定义为抽象类,需要使用这个父类进行继承与多态处理。在Java语言中设置抽象类不可以实例化对象,因为图形类不能抽象出任何一种具体图像,但它的子类却可以。
[权限修饰符] abstract class 类名 {
类体
}
[权限修饰符] abstract 方法返回值类型 方法名(参数列表);
注意:构造方法不能定义为抽象方法。
public abstract class Market {
public String name; //商场名称
public String goods; //商场名称
public abstract void shop(); //抽象方法,用来输出信息
定义一个TaobaoMarket类,继承自Market抽象类,实现其中的shop抽象方法,代码如下:
public class TaobaoMarket extends Market {
@Override
public void shop() {
//TODO Auto-generated method stub
System.out.println(name+"网购"+goods);
}
}
定义一个WallMarket类,继承自Market抽象类
public class WallMarket extends Market {
@Override
public void shop() {
//TODO Auto-generated method stub
System.out.println(name+"实体店购买"+goods);
}
}
public class GOShopping
{
public stadtic void main(String[] args)
{
Market market = new WallMarket();//使用费派生类对象创建抽象对象
Market.name = "沃尔玛";
market.goods = "七匹狼西服";
market.shop =();
market = new TaobaoMarket();//使用费派生类对象创建抽象对象
market.name = "淘宝";
market.goods = "韩都衣舍花裙";
market.shop();
}
}
使用抽象类和抽象方法时需要遵守以下原则:
(1)在抽象类中,可以包含抽象方法,也可以不包含抽象方法,但是包含了抽象方法的类必须被定义为抽象类。
(2)抽象类不能直接实例化,即使抽象类中没有声明抽象方法,也不能实例化。
(3)抽象类被继承后,子类需要实现其中所有的抽象方法。
(4)如果继承抽象类的子类也被声明为抽象类,则可以不用实现父类中所有的抽象方法。
注意:构造方法不能定义为抽象方法。
7.4.2 接口的声明及实现
接口是抽象类的延申,可以将它看作是纯粹的抽象类,接口中的所有方法都没有方法体。
接口使用关键字interface进行定义,其语法如下:
[修饰符] interface 接口名 [extends 父接口名列表] {
[public] [static] [final] 常量;
[public] [abstract] 方法;
}
一个接口实现一个接口可以使用implements关键字,代码如下:
public class Parallelogram extends Quadrangle implements drawTest {
...//
}
7.4.3 多重继承
通过接口实现多重继承的语法如下:
class 类名 implements 接口1,接口2,...,接口n
通过类实现多个接口模拟家庭成员的继承关系。
public interface IFather { //定义一个接口
void smoking(); //抽烟的方法
void goFishing(); //钓鱼的方法
}
定义一个IMother接口,并在其中定义两个方法wacthTV和cooking,代码如下:
public interface IMother { //定义一个接口
void wacthTV(); //看电视的方法
void cooking(); //做饭的方法
创建名称为Me类,继承IFather和IMother两个接口
public class Me implements IFather, IMother { //继承IFather接口和IMother接口
public void wacthTV() { //重写wacthTV()方法
System.out.println("我喜欢看电视");
}
public void cooking() { //重写cooking()方法
System.out.println("我喜欢做饭");
}
public void smoking() { //重写smoking()方法
System.out.println("我喜欢抽烟");
}
public void goFishing() { //重写goFishing()方法
System.out.println("我喜欢钓鱼");
}
public static void main(String[] args) {
// TODO Auto-generated method stub
IFather fater = new Me(); //通过子类创建IFather接口对象
System.out.println("爸爸的爱好:");
father.smoking(); //使用接口对象调用子类中实现的方法
father.goFishing();
Mother mater = new Me(); //通过子类创建IMother接口对象
System.out.println("\n妈妈的爱好:");
mather.cooking(); //使用接口对象调用子类中实现的方法
mather.wacthTV();
}
}
7.4.4 区分抽象类与接口
抽象类和接口的区别主要有以下几点:
(1)子类·只能继承一个抽象类,但可以实现任意多个接口。
(2)一个类要实现去一个接口必须实现接口中的所有方法,而抽象类不必。
(3)抽象类中的成员变量是可以各种类型,而接口中的成员变量只能是public static final的。
(4)接口中只能定义抽象方法,而抽象类中可以定义非抽象方法。
(5)抽象类中可以有静态方法和静态代码块等,接口中不可以。
(6)接口不能被实例化,没有构造方法,但抽象类可以有构造方法。
7.5 访问控制
7.5.1 访问控制符
所有访问控制符时,需要遵循以下原则。
(1)大部分顶级类都使用public修饰。
(2)如果某个类主要用作其他类的父类,该类中包含的大部分方法只是希望被其子类重写,而不想被外界直接调用,则应该使用protected修饰。
(3)类中的绝大部分属性都应该使用private修饰,除非一些static或者类似全局变量的属性,才会考虑使用public修饰;
(4)当定义的方法只是用于辅助实现该类的其他方法,应该使用private修饰;
(5)希望允许其他类自由调用的方法应该使用public修饰。
7.5.2 Java类包
在Java中采用类包机制非常重要,类包不仅可以解决类名冲突问题,还可以在开发庞大的应用程序时,帮助开发人员管理庞大的应用程序组件,方便软件复用。
在类中定义包名的语法如下:
package 包名1 [.包名2[.包名3...] ];
注意:Java包的命名规则是全部使用小写字母,另外,由于包名将转换为文件的名称,所以包名不包括特殊字符
使用包中的类,其语法如下:
import 包名1 [.包名2[.包名3...] ].类名;
import com.lzw.*; //指定 com.lzw包中的所有类在程序中都可以使用
import com.lzw.Math ///指定 com.lzw包中的Math类在程序中可以使用
7.5.3 final 关键字
1.final类
定义为final的类不能被继承
final的语法如下:
final class 类名{ }
2.final 方法
final方法不能被覆盖,定义一个为private的方法隐式被指定为final类型,这样无需将一个定义为private的方法再定义为final类型,例如下面:
private final void test() {
...//省略一些程序代码
}
3、final 变量
final 关键字可用于变量声明(定义的变量必须在声明时对其进行赋值操作) ,一旦该变量被设定,就不可以再改变该变量的值。
final double PI=3.14;
7.6 内部类
7.6.1 成员内部类
1、成员内部类简介
在一个类中使用内部类,可以在内部类中直接存取其所在类的私有成员变量。
在内部类中可以随意使用外部类的成员方法以及成员变量。
成员内部类的语法如下:
public class OuterClass { //外部类
private class InnerClass { //内部类
//...
}
}
例如,在主方法中实例化一个内部类对象。
public class void main(String args[]) {
OuterClass out = new OuterClass();
OuterClass.innerClass in =out.doit();
OuterClass.innerClass in2=out.new innerClass(); //实例化内部类对象
、使用this关键字获取内部类与外部类的引用
如果在外部类中定义的成员变量与内部类的成员变量名称相同,可以使用this关键字。
使用成员内部类时,应该遵循以下原则:
(1)可以有各种修饰符,可以用private、public、protectd、static、final 、abstract等修饰符。
(2)如果有内部类有static限定,就是类级别的,否则为对象级别.类级别可以通过外部类直接访问,对象级别需要先生成外部类的对象后才能访问;
(3)内部类不能同名;
(4)非静态内部类中不能声明任何static成员;
(5)内部类可以互相调用;
public class TheSameName {
private int x;
private class Inner {
private int x = 9;
public void doit (int_x) {
x++; //调用的是形参x
this.x++; //调用内部类的变量x
TheSameName.this.x++; //调用外部类的变量x
}
}
}
7.6.2 局部内部类
局部类不仅可以在类中进行定义,也可以在类的局部位置定义,如在类的方法或任意的作用域中均可以定义内部类。
interface OutInterface2 {
}
class OuterClass3 {
public OutInterface2 doit (final String x) { //doit()方法参数为final类型
//在doit()方法中定义一个内部类
class InnerClass2 implements OutInterface2 {
InnerClass2(String s) {
s = x;
System.out.println(s);
}
}
return new InnerClass2("doit");
}
}
7.6.3 匿名内部类
匿名类所有实现代码都需要在大括号之间进行编写。语法如下:
return new A() { //A指类名
...//内部类体
};
使用匿名内部类时应该以下原则:
(1)匿名类没有构造方法
(2)匿名类不能定义静态的成员
(3)匿名类不能用private、public、protectd、static、final 、abstract等修饰
(4)只可以创建一个匿名类实例
7.6.4 静态内部类
在内部类前添加修饰符static ,这个内部类就变为静态内部类了。
静态内部类具有以下两个特点:
1)如果创建静态内部类的对象,不需要创建其外部类的对象;
(2)不能从静态内部类的对象中访问非静态外部类的对象。
public class StaticInnerClass {
int x = 100;
static class Inner {
void doitInner() {
//System.out.prinln("外部类"+x); //不能调用外部类的成员变量x
}
}
}
在静态内部类中定义主方法
+ public static void main(String args[]) {
System.out.prinln();
7.6.5 内部类的继承
内部类和其他普通类一样可以被继承,但是继承内部类比继承普通类复杂,需要设置专门的语法来完成。
public class OutputInnerClass extends ClassA.ClassB {
public OutputInnerClass(ClassA a) {
a.super();
}
}
class ClassA {
class ClassB {
}
}
在某个类继承内部类时,必须硬性给予这个类带参数的构造方法,并且该构造方法的参数必须是该内部类的外部类引用。