——- 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。
上面是一个非常简单的表述,但我们有许多细节需要深入:
- 首先看等号的右侧。new是在内存中为对象开辟空间。具体来说,new是在内存的堆(heap)上为对象开辟空间。这一空间中,保存有对象的数据和方法。
- 再看等号的左侧。aPerson指代一个Human对象,被称为对象引用(reference)。实际上,aPerson并不是对象本身,而是类似于一个指向对象的指针。aPerson存在于内存的栈(stack)中。
- 当我们用等号赋值时,是将右侧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