• Java_三大特征相关


    重写

    子类通过重写父类的方法, 可以用自身的行为替换父类的行为

    重写的三个要点:

    • "==" :方法名, 形参列表, 返回值类型相同
    • "<=" : 返回值类型和声明异常类型, 子类小于等于父类
    • ">=" : 访问权限, 子类大于等于父类. 重写的方法不能使用比被重写方法更严格的访问权限
    public class TestOverride {
    	public static void main(String[] args) {
    		Vehicle v1 = new Vehicle();
    		Vehicle v2 = new Horse();
    		Vehicle v3 = new Plane();
    		
    		v1.run();
    		v2.run();
    		v3.run();
    		
    		v1.stop();
    		v2.stop();
    		v3.stop();
    	}
    }
    
    class Vehicle {
    	public void run() {
    		System.out.println("跑.....");
    	}
    	public void stop() {
    		System.out.println("停止不动");
    	}
    }
    
    class Horse extends Vehicle {
    	public void run() {
    		System.out.println("嘚嘚......");
    	}
    }
    
    class Plane extends Vehicle {
    	public void run() {
    		System.out.println("咻......");
    	}
    	public void stop() {
    		System.out.println("根本停不下来");
    		super.stop();		// 通过super调用父类Vehicle中被覆盖的stop函数
    	}
    }
    
    /*执行结果
    跑.....
    嘚嘚......
    咻......
    停止不动
    停止不动
    根本停不下来
    停止不动
    */
    

    对象的类型转型

    父类引用指向子类对象, 称这个过程为向上转型, 属于自动类型转换, 向上转型后的父类引用变量只能调用它编译类型的方法, 不能调用它运行时的方法. 这时需要进行类型的强制转换, 称之为向下转型, 在向下转型过程中, 必须将引用变量转换成真实的子类类型(运行时类型), 否则会出现转换异常ClassCastException

    子类转换为父类: 自动转换

    • 上转型对象不能操作子类新增的成员变量和方法
    • 上转型对象可以操作子类继承或重写的成员变量和方法
    • 如果子类重写了父类的某个方法, 上转型对象调用该方法时, 是调用的重写方法

    父类转换为子类: 强制转换

    public class TestPolym {
    	public static void main(String[] args) {
    		Animal animal = new Dog();		// 向上类型转换
    		
    		// 属性没有多态!!!
    		System.out.println(animal.age);	// 属性调用时, 仍然是基类属性, 属性没有多态
    		animal.shout();			// 调用Dog类中的shout函数
    
    		animalCry(animal);
    		
    		// 传的具体是哪一个类就调用哪一个类的方法, 大大提高了程序的可扩展性
    		// 如果没有多态, 这里需要写很多重载方法, 如果增加一种动物, 就需要重载一种动物的叫法, 非常麻烦
    		// 有了多态后, 只需要增加这个类继承Animal基类就可以了
    		animalCry(new Dog());
    		animalCry(new Cat());
    		
    		//animal.gnawBone();	// 直接通过animal来调用Dog中定义的gnawBone报错
    								// 多态不能调用声明类型中没有的方法		
    		
    		// 编写程序时, 如果想调用运行时类的方法, 只能进行类型转换, 不然通不过编译器检查
    		Dog dog = (Dog) animal;
    		dog.gnawBone(); 
    		
    		System.out.println(dog instanceof Animal);
    		System.out.println(animal instanceof Cat);
    		System.out.println(animal instanceof Dog);
    		
    		Dog d = new Dog();
    		animalCry(d);
    	}
    		
    	static void animalCry(Animal a) 
    	{
    		a.shout();
    	}
    }
    
    class Animal {
    	int age = 10;
    	
    	public void shout() {
    		System.out.println("叫了一声");
    	}
    }
    
    class Dog extends Animal {
    	int age = 28;
    	
    	public void shout() {
    		System.out.println("旺旺");
    	}
    	
    	public void gnawBone() {
    		System.out.println("在啃骨头");
    	}
    }
    
    class Cat extends Animal {
    	int age = 18;
    	
    	public void shout() {
    		System.out.println("喵喵");
    	}
    }
    /*
    10
    旺旺
    旺旺
    旺旺
    喵喵
    在啃骨头
    true
    false
    true
    旺旺
    */
    

    抽象类和抽象方法

    抽象类是一种模板, 为所有子类提供一个通用模板, 子类可以在这个模板基础上进行扩展
    通过抽象类可以避免子类设计的随意性, 这样就可以做到严格限制子类的设计, 使子类之间更加通用

    抽象方法, 使用abstract修饰的方法, 没有方法体, 只有生命. 定义的是一种规范, 子类必须给抽象方法提供具体的实现

    要点:

    抽象方法和抽象类都必须使用abstract来修饰
    抽象方法没有方法体, 只需要声明不需要实现

    含有抽象方法的类只能or必须定义抽象类
    相反, 抽象类里的方法不一定全是抽象方法, 也可以没有抽象方法

    抽象类可以包含属性, 方法, 静态初始化块, 构造方法
    抽象类不能实例化, 及不能用new来实例化抽象类, 只能用来被子类调用
    抽象类只能用来继承
    抽象方法必须被子类实现, 抽象类的子类必须覆盖所有的抽象方法才能被实例化, 否则还是抽象类

    public class Test {
    	public static void main(String[] args) {
    		Animal test_1 = new Dog(); 	// 抽象类能够实现多态
    		test_1.shout();
    		//test_1.haha();			// 多态不能调用声明类型用没有的方法
    		
    		Dog test_2 = new Dog();
    		test_2.haha();
    	}
    }
    
    abstract class Animal {
    	static {
    		System.out.println("Static method in abstract class");
    	}
    	abstract void shout();	// 抽象类方法没有方法体
    }
    
    class Dog extends Animal {
    	static {
    		System.out.println("Static method in class Dog");
    	}
    
    	void shout() {			// 必须重写父类的抽象方法, 否则编译不通过
    		System.out.println("旺旺!!!");
    	}
    	
    	void haha()
    	{
    		System.out.println("这句是来搞笑的");
    	}
    }
    /*
    Static method in abstract class
    Static method in class Dog
    旺旺!!!
    这句是来搞笑的
    */
    

    接口

    接口与类的区别:

    接口是比"抽象类"还抽象的"抽象类", 可以更加规范的对子类进行约束. 全面的专业的实现: 规范和具体实现的分离
    接口就是规范, 定义的是一组规则, 体现了现实世界中"如果能..., 则必须..."的意思
    接口的本质是契约, 定制好后大家都需遵守
    项目的具体需求是多变的, 必须以不变应万变才能从容开发, 此处的"不变"就是"规范"

    接口相关规则:

    接口中所有方法都是抽象的
    即使没有显式的将接口中的成员用public标示, 也是public访问类型
    接口中变量默认用public static final标示, 所有接口中定义的变量就是全局静态常量
    接口中方法默认用public abstract表示

    可以定义一个新接口, 用extends区继承一个已有的接口
    可以定义一个类, 用implements去实现一个接口中所有方法
    可以定义一个抽象类, 用implements去实现一个接口中部分方法

    从接口的实现者角度来开: 接口定义了可以向外提供的服务
    从接口的调用者角度来看: 接口定义了实现者能提供的服务

    格式:
    [访问修饰符] interface 接口名 [extends 父接口1, 父接口2, ...] {
    常量定义 // 总是: public static final
    方法定义 // 总是: public abstract
    }

    接口的实现

    子类通过implements来实现接口中的规范
    接口不能创建实例, 但是可以用于声明引用变量类型
    一个类实现了接口, 必须事项接口中所有的方法, 并且这些方法只能是public
    Java的类只支持单继承, 接口支持多继承
    JDK1.7之前, 接口中只能包含静态常量, 抽象方法, 不能有普通属性, 构造方法, 静态初始化块, 普通方法
    JDK1.8之后, 接口中包含普通静态方法-------------------->
    待解决

    1. 普通类: 具体实现
    2. 抽象类: 具体实现, 规范
    3. 接口: 规范
    /*******MyInterface.java*********/
    
    public interface MyInterface {
    	/* public static final */ int MAX_AGE = 10;
    	
    	/* public abstract */ void test_1();
    }
    
    class MyClass implements MyInterface {
    	
    	@Override
    	public void test_1() {
    		System.out.println(MAX_AGE);
    		System.out.println("Myclass.test_1()");
    	}
    }
    
    interface A {
    	int a = 13;
    	void test_in_A();
    }
    
    interface B {
    	void test_in_B();
    }
    
    // 接口多继承 C继承了A中的a
    interface C extends A, B{
    	void test_in_C();
    	
    	static void hahaha() {
    		System.out.println("静态方法");
    	}	// 普通静态方法
    }
    
    // 接口实现
    class Test implements C {
    	public void test_in_A() {
    		System.out.println("A");
    		System.out.println(A.a);
    	}
    	public void test_in_B() {
    		System.out.println("B");
    	}
    	public void test_in_C() {
    		System.out.println("C");
    		System.out.println(C.a);
    		C.hahaha();
    	}
    }
    
    /**********testInterface.java****************/
    public class testInterface {
    
    	public static void main(String[] args) {
    		MyClass myclass = new MyClass();
    		myclass.test_1();
    		// 不能通过继承直接使用C中的静态方法
    		//myclass.hahaha(); 	
    		
    		System.out.println("###########分隔符############");
    		
    		Test myclass_2 = new Test();
    		myclass_2.test_in_A();
    		myclass_2.test_in_B();
    		myclass_2.test_in_C();
    		
    		System.out.println("###########分隔符############");
    		
    		// 接口实现多态!!!
    		A myclass_3 = new Test();
    		myclass_3.test_in_A();
    		// 属性没有多态, Test类继承接口A中的a
    		System.out.println(myclass_3.a);
    		
    	}
    }
    
    /*	执行结果
    10
    Myclass.test_1()
    ###########分隔符############
    A
    13
    B
    C
    13
    静态方法
    ###########分隔符############
    A
    13
    13
    */
    
  • 相关阅读:
    关于SQL Server系统数据库详解
    如何删除发布服务器distribution
    SQL Server如何删除多余tempDB文件
    SQL Server 中用While循环替代游标Cursor的解决方案
    理解性能的奥秘——应用程序中慢,SSMS中快(4)收集解决参数嗅探问题的信息
    第十六章——处理锁、阻塞和死锁(3)——使用SQLServer Profiler侦测死锁
    第十六章——处理锁、阻塞和死锁(2)——侦测阻塞和阻塞查询
    降级与熔断
    浅淡缓存
    小P的架构生活(下)
  • 原文地址:https://www.cnblogs.com/hesper/p/9711333.html
Copyright © 2020-2023  润新知