黑马程序员 第七篇 继承 (part 1) (Foundation; completed)

——- android培训java培训、期待与您交流! ———-

目录
1.什么是继承
2.修饰符
3.成员变量的覆盖
4.对象引用
5.方法的重写和重载

1.什么是继承

Java提供了单一继承,通过接口可以实现多重继承。

日常生活中,我们常遇到类似自行车和公路赛车的问题
自行车有颜色大小之分,公路赛车同样也有颜色大小之分,也多了一项特殊属性即速度的优势;自行车有的属性,公路车也有;公路车有的,自行车不一定有。

在Java中,遇到此类问题,可以通过继承来完成处理这类情况的功能。继承节省了定义新类中的大量工作,大大提高了代码的重用性。

//创建一个自行车类
public class bike
{
    public Sstring color'
    public int size;
}

//创建一个公路车赛车类
public class racing_cycle
{
    public String color;
    public int size;
    public String speed;
}

代码解析:既然公路赛车是自行车的一种,我们可以用自行车类定义自行车,然后通过继承来使公路赛车获得自行车的所有属性,而公路赛车类只需要定义自己所特有的属性和状态。

就好比公路赛车是自行车的一个升级版本,很自然地拥有了自行车的特性。

通过继承来简化上面的程序

public class bike
{
    public String color;
    public int size;
}
public class racing_cycle extends bike
{
    public String speed;
}

Java提供了单一继承,通过接口可以实现多重继承。

1.1 类的继承 (extends)

在Java中,被继承的类叫超类(super),继承超类的类叫做子类(subclass)。
因此,子类是超类的一个功能上的扩展,它继承了超类定义的所有属性和方法,并且添加了特有的功能方法。

所有的类都继承自Java.lang.Object类,所以说Object类是Java中所有类的父类。如果在定义的类中不做特殊的规定,自己定义的类均直接继承自Object类。

特性总结:

  • 通过继承定义类,可以简化类的定义,让所需要的功能相应的子类去定义和实现
  • Java是单继承的,子类可以有很多,父类只能有一个。
  • Java的继承是多层继承,一个类可以有很多子类,而子类下面又可以有很多子类
  • 父类里的属性和方法可以使子类同样拥有,而子类的不能调用父类的方法和属性,子类的午餐构造器默认是调用父类的无参构造器。
  • 父类没有定义一个无参的构造器,那么编译器就默认生成一个午餐的构造器,也可以在子类构造器里显示使用super方法调用父类构造器,super方法里写几个参数就可以表示调用的是父类的哪一个构造器。
  • 一般情况下,定义了一个有参的构造器,就应该定义一个无参的构造器

1.2 继承的语法

语法
class 类名 extends 父类名称

2.修饰符

在定义类的一个成员变量和方法时,必须要指定成员变量或方法的访问权限,这时就需要使用到修饰符。修饰符是修饰的当前成员变量的访问限制和状态的。Java中的修饰符主要有public,protected,private,static和final。

修饰成员变量的修饰符主要有4个 public private default protected

这里写图片描述

2、final修饰符
final的意思是不可变,他可以修饰类、字段、方法。修饰类后类不能被扩展(extends),也就是不能被继承。修饰字段后字段的值不能被改变,因此如果有final修饰字段,应该对字段进行手动初始化。修饰方法后该方法不能被改变,也就是重写。
3、abstract修饰符
abstract是抽象的意思,用来修饰类和方法,修饰类后,该类为抽象类,不能被实例化,必需进行扩展。修饰方法后,该方法为抽象方法必须被子类重写(override)。
4、static修饰符
static用来修饰内部类,方法,字段。修饰内部类说明该内部类属于外部类而不属于外部类的某个实例。修饰字段说明该字段属于类而不属于类实例。修饰方法说明该方法属于类而不属于类实例。

详细参考
Java修饰符全解:

http://www.cnblogs.com/leokou/archive/2011/06/30/2094282.html

3.成员变量的覆盖

class fruit
{

    static String color = "蓝色";
    String size = "大";

    static String getFruirColor()
    {
        return color;   
    }

    String getFruitSize()
    {
        return size;
    }


}

public class apple extends fruit
{
    static String appleColor = "红色";
    String appleSize = "小";

    static String getFruitColor()
    {
        return appleColor;
    }

    String getFruitSize();
    {
        return appleSize;
    }


    public static void main(String[] args)
    {

        fruit f = new apple();
        System.out.println(f.getFruitColor());
        System.out.println(f.getFruitSize());


    }
}


输出结果

打印    蓝色
        小


静态方法无法重写

所有getFruitColor 返回蓝色

getFruitSize被重写返回小

4.对象引用

外部可以调用类来创建对象,比如上面在Test类中:

Human aPerson = new Human(160);

创建了一个Human类的对象aPerson。

上面是一个非常简单的表述,但我们有许多细节需要深入:

  1. 首先看等号的右侧。new是在内存中为对象开辟空间。具体来说,new是在内存的堆(heap)上为对象开辟空间。这一空间中,保存有对象的数据和方法。
  2. 再看等号的左侧。aPerson指代一个Human对象,被称为对象引用(reference)。实际上,aPerson并不是对象本身,而是类似于一个指向对象的指针。aPerson存在于内存的栈(stack)中。
  3. 当我们用等号赋值时,是将右侧new在堆中创建对象的地址赋予给对象引用。

这里的内存,指的是JVM (Java Virtual Machine)虚拟出来的Java进程内存空间。内存的堆和栈概念可参考Linux从程序到进程。

这里写图片描述

参考资料
作者:Vamei 出处:http://www.cnblogs.com/vamei
对象引用
http://www.cnblogs.com/vamei/archive/2013/04/01/2992484.html

5.方法的重写和重载

5.1 方法重写的特点
5.2 方法重载的特点
5.3 重写的返回类型
5.4 重写是基于继承的
5.5 静态方法是不能重写的
5.6  三者之间的关系 
5.7 重写toString方法

5.1 方法重写的特点

方法重写也可以叫方法的覆盖,关键词为override。在子类本身的方法中,如果和所继承的方法具有相同的名称,便构成了方法的重写。重写的特点就是能够为各个子类定义特有行为。

静态方法不可重写。

关于自行车和公路赛车的相同点和不同点例子

class bike
{
    public void move()
    {
        System.out.println("速度慢的!");
}

public class racing_cycle extends bike
{

    public void move()
    {
        System.out.println("速度快的!");
    }

    public static void main(String[] args)
    {

        racing_cycle rc = new racing_cycle();
        rc.move();

    }

}

输出结果

打印    速度快的!

问题 如果把

racing_cycle rc = new racing_cycle();
换成

bike rc = new racing_cycle();

5.2 方法重载的特点

方法的重载就是指在一个类中,存在两个或者两个以上具有相同名称,不同参数的方法。

Java里重载的关键字为overload。

  • 重载的方法名称相同,但方法的参数列表不同。如参数个数和参数类型等。
  • 重载的方法和返回值可以相同也可以不相同。

示例代码如下

public String move() {}
public String move(String name) {}
public void move(String name, int spend) {}

代码说明:

  • 虽然3种方法的名称是相同的,但这3种方法的参数列表,即个数和类型,是不相同的。
  • 判断方法是否重载,看参数列别是很重要的。

一个重载的例子

class math
{
    public int add(int i, int j)
    {
        return i+j;
    }

    public float add(float i, float j)
    {
        return i+j;
    }

    public static void main(String args[])
    {
        math m = new math();
        System.out.println(m.add(1.0f, 2.3f));
        System.out.println(m.add(1, 2));
    }
}

输出结果:

打印  3.3
      3

5.3 重写的返回类型

方法有它的返回类型,而重写的方法也有返回类型,并有一些相应的限制。方法被重写后,返回的类型为基本类型时,重写方法的返回要必须一样,否则会出现错误。

如果返回类型是对象引用类型,重写的方法返回类型可以相同,也可以派生(父类的派生类,即子类)自被重写方法的返回类型。

以下演示一段错误的使用返回类型的代码

class math
{
    public int add()
    {
        return 10 + 15;
    }

}



public class son extends math
{
    public float add()
    {
        return 10 + 15;
    }


    public static void main(String[] args)
    {
        math m = new son();
        System.out.println(m.add());
    }
}


运行结果:

    代码编译不通过
因为该代码重写add() 但返回类型改变了,所以出错。

5.4 重写是基于继承的

重写和重载的产生是基于继承,如果没有发生继承就不会产生重写和重载了。在实际开发中,一定要注意继承是重写的基础,没有继承就不会存在重写。

class door
{
]

class wood_Door extends door
{
}

class math
{
    static public door getMes()
    {
        return new door();
    }
}

public class Son extends math
{
    static public wood_Door getMes()
    {
        return new wood_Door();
    }

    public static void main(String[] args)
    {
        math m = new Son();
        System.out.println(m.getMes());
    }
}


输出结果:

    door@61de33


代码解析


    父类和子类的getMes是被修饰为static类型的,static关键字表示这个方法为静态方法,具有唯一性,是个类方法。因为static类型的方法不能被重写,所以方法m.getMes() 调用的是父类的方法`getMes(){return new door();}`

5.5 静态方法是不能重写的

静态方法就是被修饰为static类型的方法,在类里声明具有唯一性,不是通过类的实例化而存在的,而是通过类的建立而存在,可以理解为用关键字new创建对象了,就是把这个对象实例化了。Java中的静态方法可以被继承,但是不可以被重写。

下面代码演示来说明静态方法不能被重写

class door
{
}

class wood_Door extends door
{
}

class math
{
    static public door getMes()
    {
        return new door();
    }

}


public class Son extends math
{
    static public wood_Door getMes()
    {
        return new wood_Door();
    ]


    public static void main(String[] args)
    {
        Son m = new Son();
        System.out.println(m.getMes());
    }
}




输出结果 

打印  wood_Door@61de33

这里调用了wood_Door的getMes()方法,因为创建对象的时候使

Son m = new Son()


区别于上一段代码的

math m = new math()

  • 调用door的getMes()方法

因为编译期为math类型,又因为getMes方法被修饰为static类型的。所以对象引用m在运行期被强制转型为math类型


总结
==

 - 父类的静态方法可以被子类的静态方法覆盖
 - 父类的非静态方法不能被子类的静态方法覆盖
 - 父类的静态方法不能被子类的非静态方法覆盖
 - 覆盖用于父类和子类之间
 - 重写用在同一个类中,有相同的方法名,但参数不一样。

5.6 三者之间的关系
-----------

重写关键字是override,重载的关键字为overload,重写,重载,覆盖,都是基于继承的关系。当继承的关系放了,想用父类的方法就用super关键词来引用,如果想用新的方法了就重写,来完成新的功能需要。




对覆盖(重写也叫覆盖)的总结:
---------------

 - 覆盖的方法的参数列表必须要和被覆盖的方法的参数列表完全相同,才能达到覆盖的效果
 - 覆盖的方法的返回值必须和被覆盖的方法的返回值一致
 - 覆盖的方法锁抛出的异常必须和被覆盖的方法所抛出的异常一致,或者是其子类
 - 被覆盖的方法不能为private,否则在其子类中只是新定义了一个方法,并没有对其进行覆盖。


## 对重载的总结: ##

 - 使用重载时只能定义不同的参数列表
 - 不能通过重载的方法对返回类型,访问权限和抛出的异常来进行方法的重载

重写的总结如下
-------

 - 重写的方法存在于父类中,也存在于子类中
 - 重写的方法在运行期采用多态的形式
 - 重写的方法不能比被重写的方法有更高的访问权限
 - 重写的方法不能比被重写的方法有更多的异常


5.7 重写toString方法
----------------

toString方法是Java里Object类的方法,很多类都重写了该方法。该方法返回对象的状态信息。如果需要得到比较详细的状态信息,就需要对toString方法进行重写。

5.8 重写equals
------------

方法equals也是Object类的方法,很多类也进行了重写,一般重写equals方法是为了比较两个对象的内容是否相等。equals方法在两个比较的对象指向同一个对象的时候才会返回真值。如果需要进行比较详细的判断,就需要对equals方法进行重写。

equals的原型

public boolean equals(Object obj)
{
return (this == obj); //这里比较的是两个对象的引用
}





关于equals和==的区别总结
================

public class EqualTest {
public static void main(String[] args) {

//对于基本类型的变量。"=="和"equal"的区别 
int t1=57; 
int t2=67; 
int t3=124; 
int t4=124; 

//“==”对于基本数据类型,判断两个变量的值是否相等。 
Boolean result1=(t1==t2); 
Boolean result2=((t1+t2)==t3); 
Boolean result3=(t3==t4); 

System.out.println("/n/n-----【t1==t2】"+result1+"/n-----【(t1+t2)=t3】"+result2+"/n-----【t3=t4】"+result3); 
//“equal”不能用于基本数据类型。只能用于类变量。对于基本数据类型要用其包装类。 
Integer i1=new Integer(t1); 
Integer i2=new Integer(t2); 
Integer i3=new Integer(t3); 
Integer i4=new Integer(t4); 


Boolean ri1=i1.equals(i2); 
Boolean ri2=i3.equals(i1+i2); 
Boolean ri3=i3.equals(i4); 

System.out.println("/n/n-----【i1.equals(i2)】"+ri1+"/n-----【i3.equals(i1+i2)】"+ri2+"/n-----【i3.equals(i4)】"+ri3); 

//对于对象变量,"=="和"equal"的区别 

String st1="wasiker "; 
String st2="is super man"; 
String st3="wasiker is super man"; 
String st4="wasiker is super man"; 

Boolean b1=(st1==st2); 
Boolean b2=(st1+st2)==st3; 
Boolean b3=(st3==st4); 

System.out.println("/n/n-----【st1==st2】"+b1+"/n-----【(st1+st2)==st3】"+b2+"/n-----【st3==st4】"+b3); 

//因为对象变量的存储的是对象在内存中的路径,即内存地址。所以用“==”比较时,即使
//对象的值相等,但是他们的内存地址不同,所以==的结果为false。故“==”用于比较两
//个变量的值是否相等,而不是变量引用的对象是否相等

Boolean r1=st1.equals(st2); 
Boolean r2=(st1+st2).equals(st3); 
Boolean r3=st3.equals(st4); 

System.out.println("/n/n-----【st1.equals(st2)】"+r1+"/n-----【(st1+st2).equals(st3)】"+r2+"/n-----【st3.equals(st4)】"+r3); 

//equal用于比较两个对象是否相同。
}
}
“`

运行结果为:

—–【t1==t2】false
—–【(t1+t2)=t3】true
—–【t3=t4】true

—–【i1.equals(i2)】false
—–【i3.equals(i1+i2)】true
—–【i3.equals(i4)】true

—–【st1==st2】false
—–【(st1+st2)==st3】false
—–【st3==st4】true

—–【st1.equals(st2)】false
—–【(st1+st2).equals(st3)】true
—–【st3.equals(st4)】true

总之:
**“==”比较的是值【变量(栈)内存中存放的对象的(堆)内存地址】
equal用于比较两个对象的值是否相同【不是比地址】**

【特别注意】Object类中的equals方法和“==”是一样的,没有区别,而String类,Integer类等等一些类,是重写了equals方法,才使得equals和“==不同”,所以,当自己创建类时,自动继承了Object的equals方法,要想实现不同的等于比较,必须重写equals方法。

“==”比”equal”运行速度快,因为”==”只是比较引用.

reference:
http://blog.csdn.net/xcysuccess3/article/details/6557771

——- android培训java培训、期待与您交流! ———-

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值