zoukankan      html  css  js  c++  java
  • JavaSE Day10

    本节内容

     1.对象与对象的关系

    2.值传递/引用传递

    3.抽象类

    4.接口

    5.多态

    6.向上转型/向下转型

    一、对象与对象的关系

    Java中对象与对象的一对一关系 :

    比如我们的一对夫妇他们之间的关系就是一对一,在Java中的一对一关系,实质是将一个类当做另一个类的属性。

    package com.xk;
    /*
     *作者:吴志龙
     *日期:2018年7月30日  
    */
    public class Husband {
        
        String  name;
        
        int age;
        
        //老公与妻子的一对一关系
        
        Wife wife;
    
    }
    package com.xk;
    /*
     *作者:吴志龙
     *日期:2018年7月30日  
    */
    public class Wife {
        
          String  name;
        
          int age;
          //妻子与老公的一对一关系
          Husband husband;
          
    
    }

    Java中对象与对象的一对多关系 :

    比如我们的部门与员工之间的关系,一个部门有多个员工,这是将一个员工数组当做部门类的一个属性。

    package com.xk;
    /*
     *作者:吴志龙
     *日期:2018年7月30日  
    */
    public class Emp {
        
        int e_id;
        
        String name;
        
        int age;
        
        char sex;
        
        String address;
        
        double salary;
        
        
        
        
        
    
    }
    package com.xk;
    /*
     *作者:吴志龙
     *日期:2018年7月30日  
    */
    public class Dept {
        
        int dept_id;
        
        String  dept_name;
        //部门与员工的一对多关系
         Emp[] emp;
        
        
    
    }

    二、方法传值

    首先要说明的是java中是没有指针的,java中只存在值传递,只存在值传递!!!  然而我们经常看到对于对象(数组,类,接口)的传递似乎有点像引用传递,可以改变对象中某个属性的值。但是不要被这个假象所蒙蔽,实际上这个传入函数的值是对象引用的拷贝,即传递的是引用的地址值,所以还是按值传递

    值传递

    public class Test3 {
        public static void change(int a){
            a=50;
        }
        public static void main(String[] args) {
            int a=10;
            System.out.println(a);
            change(a);
            System.out.println(a);
        }
    }

    运行结果: 10 10

    引用传递

    public class Test3 {
        public static void change(int []a){
            a[0]=50;
        }
        public static void main(String[] args) {
            int []a={10,20};
            System.out.println(a[0]);
            change(a);
            System.out.println(a[0]);
        }
    }

     运行结果: 10  50

    String

    public class Test {
        public static void change(String s){
            s="zhangsan";
        }
        
        public static void main(String[] args) {
            String s=new String("lisi");
            System.out.println(s);
            change(s);
            System.out.println(s);
        }
    }

     运行结果:  list  list

    三、抽象类

        抽象类的定义

    普通类是一个完善的功能类,可以直接产生实例化对象,并且在普通类中可以包含有构造方法、普通方法、static方法、常量和变量等内容。而抽象类是指在普通类的结构里面增加抽象方法的组成部分。

    那么什么叫抽象方法呢?在所有的普通方法上面都会有一个“{}”,这个表示方法体,有方法体的方法一定可以被对象直接使用。而抽象方法,是指没有方法体的方法,同时抽象方法还必须使用关键字abstract做修饰

    拥有抽象方法的类就是抽象类,抽象类要使用abstract关键字声明。

    package com.xk;
    /*
     *作者:吴志龙
     *日期:2018年7月30日  
    */
    public abstract class Animal {
        //普通方法
        public  void sleep(){
            System.out.println("有方法体");
        }
        
        //抽象方法    没有方法体  使用 abstract 关键词修饰
        public abstract void eat();
    
    }

    抽象类的使用:

           抽象类不能实例化(不能创建对象)  为什么?????

    因为抽象类中存在抽象方法,我们知道一个如果能实例化,通过实例化对象就可以调用类中的属性与方法,而抽象方法没有方法体,没有方法体就不能调用,既然不能调用方法,那么也就不能实例化。

    抽象类的使用原则如下:
    (1)抽象方法必须为public或者protected(因为如果为private,则不能被子类继承,子类便无法实现该方法),缺省情况下默认为public;
    (2)抽象类不能直接实例化,需要依靠子类采用向上转型的方式处理;
    (3)抽象类必须有子类,使用extends继承,一个子类只能继承一个抽象类;
    (4)子类(如果不是抽象类)则必须覆写抽象类之中的全部抽象方法(如果子类没有实现父类的抽象方法,则必须将子类也定义为为abstract类。)

    package com.xk;
    /*
     *作者:吴志龙
     *日期:2018年7月30日  
    */
    public abstract class Animal {
        //普通方法
        public  void sleep(){
            System.out.println("有方法体");
        }
        
        //抽象方法    没有方法体  使用 abstract 关键词修饰
        public abstract void eat();
    
    }
    package com.xk;
    /*
     *作者:吴志龙
     *日期:2018年7月30日  
    */
    public class Dog extends Animal{   //dog类是Animal抽象类的子类,是一个普通类
        
        
        
         //强制重写抽象方法
        @Override
        public void eat() {  
            // TODO Auto-generated method stub
            
        }
    
    }

    现在就可以清楚的发现:
    (1)抽象类继承子类里面有明确的方法覆写要求,而普通类可以有选择性的来决定是否需要覆写;
    (2)抽象类实际上就比普通类多了一些抽象方法而已,其他组成部分和普通类完全一样;
    (3)普通类对象可以直接实例化,但抽象类的对象必须经过向上转型之后才可以得到。

    虽然一个类的子类可以去继承任意的一个普通类,可是从开发的实际要求来讲,普通类尽量不要去继承另外一个普通类,而是去继承抽象类。

    三、抽象类的使用限制

    (1)抽象类中有构造方法么?
    由于抽象类里会存在一些属性,那么抽象类中一定存在构造方法,其存在目的是为了属性的初始化。
    并且子类对象实例化的时候,依然满足先执行父类构造,再执行子类构造的顺序。

    package com.xk;
    /*
     *作者:吴志龙
     *日期:2018年7月30日  
    */
    public abstract class Animal {
        
        //构造方法
        public Animal() {
             System.out.println("Animal类的构造方法");
        }
    
        //普通方法
        public  void sleep(){
            System.out.println("有方法体");
        }
        
        //抽象方法    没有方法体  使用 abstract 关键词修饰
        public abstract void eat();
    
    }
    package com.xk;
    /*
     *作者:吴志龙
     *日期:2018年7月30日  
    */
    public class Dog extends Animal{   //dog类是Animal抽象类的子类,是一个普通类
        
        public Dog() {
             System.out.println("Dog 类的构造方法");
        }
        
         //强制重写抽象方法
        @Override
        public void eat() {  
            // TODO Auto-generated method stub
            
        }
        
        
        public static void main(String[] args) {
            //向上转型
             Animal  animal =new Dog();
            
            
        }
    
        
    
    }

    运行结果

    Animal类的构造方法
    Dog 类的构造方法

    (2)抽象类可以用final声明么?
    不能,因为抽象类必须有子类,而final定义的类不能有子类;

    抽象类的应用:抽象类是模板式设计

    例如,现在有三类事物:
    (1)机器人:充电,工作;
    (2)人:吃饭,工作,睡觉;
    (3)猪:进食,睡觉。
    现要求实现一个程序,可以实现三种不同事物的行为

    四、接口

    接口,英文称作interface,在软件工程中,接口泛指供别人调用的方法或者函数。从这里,我们可以体会到Java语言设计者的初衷,它是对行为的抽象

    [public] interface InterfaceName {
     
    }

    接口中可以含有 变量和方法。但是要注意,接口中的变量会被隐式地指定为public static final变量(并且只能是public static final变量,用private修饰会报编译错误),而方法会被隐式地指定为public abstract方法且只能是public abstract方法(用其他关键字,比如private、protected、static、 final等修饰会报编译错误),并且接口中所有的方法不能有具体的实现,也就是说,接口中的方法必须都是抽象方法。从这里可以隐约看出接口和抽象类的区别,接口是一种极度抽象的类型,它比抽象类更加“抽象”,并且一般情况下不在接口中定义变量。

    定义:

    Java接口(Interface),是一系列方法的声明,是一些方法特征的集合,一个接口只有方法的特征没有方法的实现,因此这些方法可以在不同的地方被不同的类实现,而这些实现可以具有不同的行为(功能)

    接口的特点:

     

    1. Java接口中的成员变量默认都是public,static,final类型的(都可省略),必须被显示初始化,即接口中的成员变量为常量(大写,单词之间用”_”分隔);
    2. Java接口中的方法默认都是public,abstract类型的(都可省略),没有方法体,不能被实例化;
    3. Java接口中只能包含public,static,final类型的成员变量和public,abstract类型的成员方法;
    4. 接口中没有构造方法,不能被实例化;
    5. 一个接口不能实现(implements)另一个接口,但它可以继承多个其它的接口
    6. Java接口必须通过类来实现它的抽象方法;
    7. 当类实现了某个Java接口时,它必须实现接口中的所有抽象方法,否则这个类必须声明为抽象类;
    8. 不允许创建接口的实例(实例化),但允许定义接口类型的引用变量,该引用变量引用实现了这个接口的类的实例;
    9. 一个类只能继承一个直接的父类,但可以实现多个接口,间接的实现了多继承。

    现在有这样一个需求:

             现在学校的招待环境:  招待的人员有: 学生   老师   家长

    学生:  在食堂吃饭、在宿舍住宿

    老师:教师食堂    、学校公寓

    家长: 招待所吃饭  、招待所

    理论上,当然可以对每个不同身份的人各定义一个对应的类,并实现各自的方法,但是观察这写类,可以归纳出其有一个共同的模板,即“人”的“食、宿”问题。这时候,就可以发挥接口的功能了

    interface Person{  
        void eat();  
        void sleep();  
    }  
    
    class Student implements Person{  
        public void eat(){  
           System.out.println("学生去食堂吃饭!");  
        }  
        public void sleep(){  
           System.out.println("学生回寝室睡觉!");  
        }  
    }  
    
    class Teacher implements Person{  
        public void eat(){  
           System.out.println("教师去教工餐厅吃饭!");  
        }  
        public void sleep(){  
           System.out.println("教师回学校公寓睡觉!");  
        }  
    }  
     class Parents implements Person{  
        publicvoid eat(){  
           System.out.println("家长去招待所饭馆吃饭!");  
        }  
        public void sleep(){  
           System.out.println("家长回招待所睡觉!");  
        }  
    }  
    
    public class PersonInterface{  
             public static void main(String[] args)  
             {  
                       Person p=new Student();  
                       p.eat();  
                       p.sleep();  
                       p=new Teacher();  
                       p.eat();  
                       p.sleep();  
                       p=new Parents();  
                       p.eat();  
                       p.sleep();  
             }  
    } 
    View Code

    现在需要添加一些功能,即现在需要添加“外宾、上级领导”两类角色,并且以后工具需要还要添加相应的身份角色的人进来,此时,只需要根据需要添加“外宾”类、“领导”类,而主类仍然可以拿来就用,无需进行更多的修改。此时就可以显示出接口的作用了。

    class Foreign implements Person{  
        publicvoid eat(){  
           System.out.println("外宾去酒店吃饭!");  
        }  
        public void sleep(){  
           System.out.println("外宾回酒店睡觉!");  
        }  
    }  
    
    class Leader implements Person{  
        publicvoid eat(){  
           System.out.println("领导去宾馆吃饭!");  
        }  
        public void sleep(){  
           System.out.println("外宾回宾馆睡觉!");  
        }  
    }
    View Code

    通过继承来扩展接口

    通过继承,可以很容易地在接口中添加新的方法声明,还可以通过继承在新接口中组合数个接口。

    interface Monster {// 怪物
        void menace();// 威胁
    }
    
    interface DangerousMonster extends Monster {
        void destroy();// 破坏
    }
    
    interface Lethal {// 致命的
        void kill();// 杀死
    }
    
    class DragonZilla implements DangerousMonster {
    
        @Override
        public void menace() {
            // TODO Auto-generated method stub
    
        }
    
        @Override
        public void destroy() {
            // TODO Auto-generated method stub
    
        }
    }
    
    interface Vampire extends DangerousMonster, Lethal {// 吸血鬼
        void drinkBlood();
    }
    
    class VeryBadVampire implements Vampire {
        @Override
        public void menace() {
            // TODO Auto-generated method stub
    
        }
    
        @Override
        public void destroy() {
            // TODO Auto-generated method stub
    
        }
    
        @Override
        public void kill() {
            // TODO Auto-generated method stub
    
        }
    
        @Override
        public void drinkBlood() {
            // TODO Auto-generated method stub
    
        }
    
    }
    
    public class HorrorShow {
        static void u(Monster b) {
            b.menace();
        }
    
        static void v(DangerousMonster d) {
            d.menace();
            d.destroy();
        }
    
        static void w(Lethal l) {
            l.kill();
        }
    
        static void x(Vampire v) {
            v.menace();
            v.destroy();
            v.kill();
            v.drinkBlood();
        }
    
        public static void main(String[] args) {
            DangerousMonster barney = new DragonZilla();
            u(barney);
            v(barney);
    
            Vampire vlad = new VeryBadVampire();
            u(vlad);
            v(vlad);
            w(vlad);
            x(vlad);
    
        }
    
    }
    View Code

    DangerousMonster是Monster的直接扩展,它产生了一个新接口。DragonZilla中实现了这个接口。

    在Vampire中使用的语法仅适用于接口继承。一般情况下,只可以将extends用于单一类,但是可以引用多个基类接口。

    一 接口和抽象类的相似性

    1 接口和抽象类都不能被实例化,它们都位于继承树的顶端,用于被其他类实现和继承。

    2 接口和抽象类都可以包含抽象方法,实现接口或继承抽象类的普通子类都必须实现这些抽象方法。

    二 接口和抽象类的区别

    1 接口里只能包含抽象方法,静态方法和默认方法,不能为普通方法提供方法实现,抽象类则完全可以包含普通方法。

    2 接口里只能定义静态常量,不能定义普通成员变量,抽象类里则既可以定义普通成员变量,也可以定义静态常量。

    3 接口不能包含构造器,抽象类可以包含构造器,抽象类里的构造器并不是用于创建对象,而是让其子类调用这些构造器来完成属于抽象类的初始化操作。

    4 接口里不能包含初始化块,但抽象类里完全可以包含初始化块。

    5 一个类最多只能有一个直接父类,包括抽象类,但一个类可以直接实现多个接口,通过实现多个接口可以弥补Java单继承不足。

    五、多态:

    定义:多态:指允许不同类的对象对同一消息做出响应。即同一消息可以根据发送对象的不同而采用多种不同的行为方式

    一种事物多种表现形态。

    实现多态的技术称为:动态绑定(dynamic binding),是指在执行期间判断所引用对象的实际类型,根据其实际的类型调用其相应的方法

    多态存在的三个必要条件

    一、要有继承;

    二、要有重写;

    三、父类引用指向子类对象

    Java中的多态表现有:

    静态多态: 在编译阶段体现: 方法的重载

    多态多态:在代码运行阶段体现: 方法的重写。

    多态的好处:

     提高了代码的维护性(继承保证)
     提高了代码的扩展性(由多态保证)

    六、向上转型/向下转型

    要转型,首先要有继承。继承是面向对象语言中一个代码复用的机制,简单说就是子类继承了父类中的非私有属性和可以继承的方法,然后子类可以继续扩展自己的属性及方法

      向上转型:子类对象转为父类,父类可以是接口。公式:Father f = new Son();Father是父类或接口,son是子类。

           向下转型:父类对象转为子类。公式:Son s = (Son)f;

     
    
    public class Human {
    
        public void sleep() {
            System.out.println("Human sleep..");
        }
    
        public static void main(String[] args) {
            Human h = new Male();// 向上转型
            h.sleep();
            Male m = new Male();// 干嘛要向上转型
            m.sleep();
            // h.speak();此方法不能编译,报错说Human类没有此方法
        }
    }
    
    class Male extends Human {
        @Override
        public void sleep() {
            System.out.println("Male sleep..");
        }
    
        public void speak() {
            System.out.println("I am Male");
        }
    }
    
    class Female extends Human {
        @Override
        public void sleep() {
            System.out.println("Female sleep..");
        }
    
        public void speak() {
            System.out.println("I am Female");
        }
    }
    View Code

    向上转型与向下转型可以看作是数据类型的转换:

    向上转型:可以看作是小类型转大类型  自动转换

    向下转型:可以看作是大类型转小类型  强制转换。

    向下转型:注意看转的父类引用是不是这个子类的实例,如果不是就不能转,如果是才能转。

       

          

  • 相关阅读:
    不敢想,做个博客竟如此简单!
    我有一台服务器,能干啥?
    精品 IDEA 插件大汇总!值得收藏
    怒肝半月!Python 学习路线+资源大汇总
    怒肝 Linux 学习路线,这回不难
    多环境
    分享 10 个高星的创意项目!
    js的attribute
    选择大厂该做哪些准备?|小白进入大厂现状
    小白程序猿了解大厂的开发模式
  • 原文地址:https://www.cnblogs.com/wuzhilong/p/9391736.html
Copyright © 2011-2022 走看看