Java基础笔记—第五篇(继承、重写、多态、重载、final)

**

Java基础笔记—第五篇(继承、重写、多态、重载、final)

**

1. 继承

继承—对象的一个新类可以从现有的类中派生,这个过程称为类继承。继承其实是对类的重用,提供了一种明确表述共性的方法。(私有成员也可以继承,但由于访问权限的控制,在子类中不能直接使用父类的私有成员,可以通过从父类中继承得到protected、public方法,如getter、setter方法访问)Java是单继承,一个子类只能有一个父类。

  • 当生成子类对象时,java默认先调用父类无参构造方法,然后执行该构造方法,生成父类对象;接下来调用子类的构造方法,生成子类的对象。
  • 子类用super()显示调用父类的某个对应的构造方法,也必须放在第一条执行语句。当两个方法形成重写关系时,子类调用super.run()调用父类的run方法(不必放在第一条语句执行)。

2. 重写

重写其实就是方法的覆盖

  • 子类覆盖方法和父类被覆盖方法返回类型、方法名称、参数列表必须相同;
  • 子类覆盖方法的访问权限必须大于等于父类的访问权限;(public>protected>default>private)
  • 方法覆盖只能存在于子类和父类之间;
  • 子类覆盖方法不能比父类被覆盖方法跑出更多异常。(例:父类的一个方法申明了一个检查异常IOException,在重写这个方法是就不能抛出Exception,只能抛出IOException的子类异常,可以抛出非检查异常。)

3. 多态

多态(Polymorphism):父类型的引用可以指向子类的对象。在一个类中,可以定义多个同名的方法,只要确定它们的参数个数和类型不同,这种现象称为类的多态。类的多态性体现在两方面:一是方法的重载上,包括成员方法和构造方法的重载;二是在继承过程中,方法的重写。

Java实现多态有三个必要条件:继承、重写、向上转型。

public class Wine {
    public void fun1(){
        System.out.println("Wine的fun1.....");
        fun2();
    }
    
    public void fun2(){
        System.out.println("Wine的fun2...");
    }
}

public class JNC extends Wine{
    /**
     * @desc 子类重载父类方法
     *        父类中不存在该方法,向上转型后,父类是不能引用该方法的
     * @param a
     * @return void
     */
    public void fun1(String a){
        System.out.println("JNC的fun1...");
        fun2();
    }
    
    /**
     * 子类重写父类方法
     * 指向子类的父类引用调用fun2时,必定是调用该方法
     */
    public void fun2(){
        System.out.println("JNC的fun2...");
    }
}

public class Test {
    public static void main(String[] args) {
        Wine a = new JNC();
        a.fun1();
    }
}
-------------------------------------------------
输出:
Wine的fun1.....
JNC的fun2...

向上转型:指向子类的父类引用由于向上转型了,它只能访问父类中拥有的方法和属性,而对于子类中存在而父类中不存在的方法,该引用是不能使用的,尽管是重载该方法。若子类重写了父类中的某些方法,在调用该些方法的时候,必定是使用子类中定义的这些方法(动态连接、动态调用)。

public class A {
    public String show(D obj) {
        return ("A and D");
    }

    public String show(A obj) {
        return ("A and A");
    } 

}

public class B extends A{
    public String show(B obj){
        return ("B and B");
    }
    
    public String show(A obj){
        return ("B and A");
    } 
}

public class C extends B{

}

public class D extends B{

}

public class Test {
    public static void main(String[] args) {
        A a1 = new A();
        A a2 = new B();
        B b = new B();
        C c = new C();
        D d = new D();
        
        System.out.println("1:" + a1.show(b));
        System.out.println("2:" + a1.show(c));
        System.out.println("3:" + a1.show(d));
        System.out.println("4:" + a2.show(b));
        System.out.println("5:" + a2.show(c));
        System.out.println("6:" + a2.show(d));
        System.out.println("7:" + b.show(b));
        System.out.println("8:" + b.show(c));
        System.out.println("9:" + b.show(d));      
    }
}
-------------------------------------------------
输出:
1A and A
2A and A
3A and D
4B and A
5B and A
6A and D
7B and B
8B and B
9A and D

当父类对象引用变量引用子类对象时(A a2 = new B();),被引用对象的类型不是引用变量的类型决定了调用谁的成员方法。被调用的方法必须是在父类中定义过的(public String show(A obj){}),也就是说被子类覆盖的方法;没有被子类覆盖的的方法,父类特有的方法,调用执行父类的代码块(public String show(D obj){});子类特有的方法(public String show(B obj){}),父类对象不可以调用;被子类覆盖过的方法,父类对象调用时,执行的是子类覆盖后的执行条件(return ("B and A");)。

4. 重载

重载(Overloading):方法重载是让类以统一的方式处理不同类型数据的一种手段,多个同名函数同时存在,具有不同的参数个数/类型;Java的方法重载,就是在类中可以创建多个方法,它们具有相同的名字,但具有不同的参数和不同的定义;重载的时候,方法名要一样,但是参数类型和个数不一样,返回值类型可以相同也可以不相同,无法以返回型别作为重载函数的区分标准。

重载规则:

  • 必须具有不同的参数列表;
  • 可以有不同的返回类型,只要参数列表不同就可以了;
  • 可以有不同的访问修饰符;
  • 可以抛出不同的异常;

5. final

  • final修饰类:类不能被继承,final类中所有成员都会隐式地指定为final方法。
  • final修饰方法:第一个是把方法锁定,以防任何继承类修改它的含义;第二个是效率,早期Java会将final转为内嵌调用,但如果方法过于庞大,就可能看不到内嵌调用带来的任何性能提升,最近版本中,不需要使用final优化啦。
    • 父类的final方法是不能被子类覆盖的,也就是说子类是不能够存在和父类一模一样的方法的,不能被重写(可以重载多个final修饰的方法);如果父类中final修饰的方法同时访问权限为private,将会导致子类中不能直接继承到此方法,此时,就可以在子类中定义相同方法名和参数的方法,不再产生重写与final的矛盾,而是在子类中定义了新的方法。(类的private方法会隐式地被指定为final方法)。
  • final修饰变量: final修饰一个成员变量表示常量,只能被赋值一次,赋值后值不再改变。
    • 当final修饰一个基本数据类型时,表示该基本数据类型的值一旦初始化后便不能发生变化;
    • 当final修饰一个引用类型时,则在对其初始化之后便不能在让其指向其他对象了,但该引用所指向的对象的内容是可以发生变化的;
    • 当函数的参数类型声明为final时,说明该参数只读,即可以读取,但不可以修改。
public class Test {
    public static void main(String args[]){
		String a = "hello2";
		final String b = "hello";
		String d = "hello";
		String c = b+2;
		String e = d+2;
		System.out.println((a == c));
		System.out.println((a == e)); 
	}
}
-------------------------------------------------
输出:
true
false

当final变量是基本数据类型或String类型时,如果在编译期间能知道它的确切值,则编译器会把它当做编译器常量使用。

public class Test {
    public static void main(String args[]){
		String a = "hello2";
		final String b = getHello();
		String c = b+2;
		System.out.println((a == c)); 
	}
	
	public static String getHello(){
		return "hello";
	}
}
-------------------------------------------------
输出:
false
  • final参数
public class TestFinalParam{
	public static void main(String args[]){
		TestFinalParam testFinalParam = new TestFinalParam();
		StringBuffer buffer = new StringBuffer("hello");
		testFinalParam.changeValue(buffer);
		System.out.println(buffer);
	}

	public void changeValue(final StringBuffer buffer){
		//buffer重新指向另一个对象,final修饰引用类型的参数时,不能让其再指向其他对象,但是对其指向的内容可以修改
		buffer = new StringBuffer("hi"); //如果参数中有final关键字,这里会报错,如果没有正常执行
		buffer.append("world");
		System.out.println(buffer);
	}
}
-------------------------------------------------
若参数中有final关键字输出:
报错
若参数中没有final关键字输出:
hiworld
helloworld
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值