1 继承的概述
package java007;
/**
* 2017/9/9
* 说明:学生
*/
public class Student {
String name;
int age;
public void study(){
System.out.print("我叫"+name+",今年"+age+",我是一名学生,正在学习");
}
}
package java007;
/**
* 2017/9/9
* 说明:工人
*/
public class Worker {
String name;
int age;
public void work(){
System.out.print("我叫"+name+",今年"+age+",我是一名工人,正在工作");
}
}
package java007;
/**
* 2017/9/9
* 说明:
*/
public class StudentAndWorkderTest {
public static void main(String[] args) {
Student s = new Student();
s.name = "张三";
s.age = 15;
s.study();
Worker w = new Worker();
w.name = "李四";
w.age = 34;
w.work();
}
}
-
- 我们可以发现学生类和工人类中都有姓名和年龄属性,属于重复字段,那么如何解决?,且看如下代码。
package java007;
/**
* 2017/9/9
* 说明:
*/
public class Person {
String name;
int age;
}
package java007;
/**
* 2017/9/9
* 说明:学生
*/
public class Student extends Person {
public void study(){
System.out.print("我叫"+name+",今年"+age+",我是一名学生,正在学习");
}
}
package java007;
/**
* 2017/9/9
* 说明:工人
*/
public class Worker extends Person{
public void work(){
System.out.print("我叫"+name+",今年"+age+",我是一名工人,正在工作");
}
}
package java007;
/**
* 2017/9/9
* 说明:
*/
public class StudentAndWorkderTest {
public static void main(String[] args) {
Student s = new Student();
s.name = "张三";
s.age = 15;
s.study();
Worker w = new Worker();
w.name = "李四";
w.age = 34;
w.work();
}
}

- 继承的好处:
- ①提高了代码的复用性。
- ②让类与类之间产生关系,给第三个特征多态提供了前提。
2 继承的特点
- Java中支持单继承(一个子类只能有一个父类),不直接直接多继承,支持多层继承。
3 super关键字
- 当本类的成员变量和局部变量同名的时候,使用this区分。
- 当子父类的成员变量同名的时候,使用super区分父类。
- this和super的用法很相似。
package java007;
/**
* 2017/9/9
* 说明:
*/
class Fu{
private int age = 20;
public void show(){
int age = 10;
System.out.print("局部变量:"+age+",成员变量:"+this.age);
}
}
public class ExtendsDemo {
public static void main(String[] args) {
Fu f = new Fu();
f.show();
}
}

-
-
解释说明:
- ①先使用javac ExtendsDemo.java命令将ExtendsDemo编译成class文件,当然,顺便将Fu.java也编译成class文件。
- ②使用java ExtendsDemo命令,虚拟机会从方法区中,将main()方法识别,并加载到栈中。
- ③执行了new Fu();会在堆内存中开辟一个空间,(将Fu(){}加载到栈内存中,因为这一部分对本程序而言不是很重要,所以省略相关描述),用来存储对象,并初始化age=0。然后执行到private int age = 20;的时候,就将20赋值给age,此时age在堆内存中是20。
- ④Fu f = new Fu();main()方法所在的栈内存中,开辟了一个引用变量f,然后将堆内存中的对象的地址赋值给f,那么此时f就指向堆内存中的对象。
- ⑤f.show();从方法区将show()方法加载到栈中,此时,注意的是,show()方法内部就包含了this关键字,同时f变量的地址值给了this,因为this表示的是当前对象的引用,而调用show()方法的恰恰是f,所有this和f此时的值是相同的,那么show()方法也指向了堆内存中的对象,然后在show()方法内部开辟了一个age变量,这个age变量是栈内存中show()方法内部的局部变量,而想获取堆内存中的age变量,只能通过show()方法内存的this关键字了。
package java007;
/**
* 2017/9/9
* 说明:
*/
class Fu{
int age1 = 20;
}
class Zi extends Fu{
int age2 = 30;
public void show(){
System.out.print(age1+" "+age2);
}
}
public class ExtendsDemo {
public static void main(String[] args) {
Zi z = new Zi();
z.show();
}
}

-
-
解释说明:通过上面的程序貌似可以这样解释,第一,变量名是不一样的,第二,子类是继承了父类,而子类中没有age1成员变量,所以从父类中继承(拷贝)了age1成员变量。
package java007;
/**
* 2017/9/9
* 说明:
*/
class Fu{
int age = 20;
}
class Zi extends Fu{
int age = 30;
public void show(){
System.out.print(age);
}
}
public class ExtendsDemo {
public static void main(String[] args) {
Zi z = new Zi();
z.show();
}
}
package java007;
/**
* 2017/9/9
* 说明:
*/
class Fu{
int age = 20;
}
class Zi extends Fu{
int age = 30;
public void show(){
System.out.print(age+" "+super.age);
}
}
public class ExtendsDemo {
public static void main(String[] args) {
Zi z = new Zi();
z.show();
}
}
-
-
解释说明:通过上面的程序貌似可以这样解释,子类和父类成员变量相同的时候,子类可以将父类相同成员变量覆盖,其实不然,且看下面分解。

4 函数覆盖(重写)
package java007;
/**
* 2017/9/10
* 说明:
*/
class Fu{
public void show1(){
System.out.print("Fu的show1方法");
}
}
class Zi extends Fu{
public void show2(){
System.out.print("Zi的show2方法");
}
}
public class ExtendsDemo2 {
public static void main(String[] args) {
Zi z = new Zi();
z.show1();
z.show2();
}
}

package java007;
/**
* 2017/9/10
* 说明:
*/
class Fu{
public void show(){
System.out.print("Fu的show方法");
}
}
class Zi extends Fu{
public void show(){
System.out.print("Zi的show方法");
}
}
public class ExtendsDemo2 {
public static void main(String[] args) {
Zi z = new Zi();
z.show();
}
}

- 当子类中出现成员函数和父类的一样的时候,会运行子类的成员函数,从表现上看。好像是子类的成员函数“覆盖”了父类的成员函数,这种现象,被称为重写或者覆盖。
- 函数的两个特性:
- 重写的注意事项:子类方法覆盖父类方法时,子类方法的权限必须>=父类方法的权限。
5 子类的实例化过程
package java007;
/**
* 2017/9/10
* 说明:
*/
class Fu{
public Fu(){
System.out.println("Fu的构造方法");
}
}
class Zi extends Fu{
public Zi(){
System.out.println("Zi的构造方法");
}
}
public class ExtendsDemo2 {
public static void main(String[] args) {
Zi z = new Zi();
}
}

- 在子类构造对象的时候,发现,访问子类构造函数的时候,父类也运行了。这是为什么?因为,在子类构造方法中的第一行有一个默认的隐式语句:super();j如下代码所示。
package java007;
/**
* 2017/9/10
* 说明:
*/
class Fu{
public Fu(){
System.out.println("Fu的构造方法");
}
}
class Zi extends Fu{
public Zi(){
super();//调用的是父类的默认的空参数构造函数
System.out.println("Zi的构造方法");
}
}
public class ExtendsDemo2 {
public static void main(String[] args) {
Zi z = new Zi();
}
}

package java007;
/**
* 2017/9/10
* 说明:
*/
class Fu{
public Fu(){
show();
}
public void show(){
System.out.print("fu show");
}
}
class Zi extends Fu{
int num = 8;
public Zi(){
}
public void show(){
System.out.print("zi show:"+num);
}
}
public class ExtendsDemo2 {
public static void main(String[] args) {
Zi z = new Zi();
z.show();
}
}

6 final关键字
- final可以修饰类、方法和变量。
- final修饰的类不可以被继承。
- final修饰的方法不可以被重写。
- final修饰的变量是一个常量,只能被赋值一次。
- 内部类只能访问被final修饰的局部变量。
class Person{
private final int age = 10;
}
class Person{
private final int age ;
{
age = 20;
}
}
class Person{
private final int age ;
public Person(int age){
this.age = age;
}
}