zoukankan      html  css  js  c++  java
  • Java学习日记基础(五)——类、对象之this、静态变量(类变量)、静态方法(类方法)、四大特征

    this

    赵本山问奥尼尔:“我的爸爸的爸爸是谁?”

    奥尼尔:“不知道”

    赵本山:“你傻啊,是我爷爷”

    奥尼尔回去问科比:“我的爸爸的爸爸是谁?”

    科比:“不知道”

    奥尼尔:”你傻啊,是赵本山的爷爷“

    就像这个笑话一样,不同的人,用this时,指向的对象也是变的。

     普通方法中,this总是指向调用该方法的对象

    //this在成员方法中的用处
    //this就是指代当前对象,是一个隐式参数
    
    public class thissss
    {
    	public static void main(String []args)
    	{
    		Student s1 = new Student();
    		s1.name = "小白";
    		s1.age = 17;
    		s1.study();
    		System.out.println(s1.name);
    		Student s2 = new Student();
    		s2.name = "小徐";
    		s2.age = 18;
    		s2.study();
    	}
    }
    
    
    class Student
    {
    	int age;
    	String name;
    	public void study()		
    	//在创建成员方法(函数)的时候会自动传一个this参数,指向该对象的地址,但是是隐藏的
    	{
    		this.name = "小黑";
    		//s1.name = "小黑";
    		//这条语句是错误的,因为对象要在类创建完成之后才有
    		//但是使用this.name就可以给类进行赋值
    		//因为this指向创建的对象的地址,所以this.name就会找到该对象中study()方法的地址
    		//对这个地址进行操纵,总而更改当前对象的值
    		System.out.println(name+"在学习");
    	}
    }
    

    图解:

    构造方法中,this总是指向正要初始化的对象

    //this在构造方法中的用处
    //用来指向正在初始化的对象
    public class thissss2
    {
    	public static void main(String []args)
    	{
    		Student s1 = new Student(17);
    		System.out.println(s1.age);
    		Student s2 = new Student(18);
    
    	}
    }
    
    
    class Student
    {
    	int age;
    	String name;
    	public Student(int age)
    	{
    		//age = age
    		//直接写age指代的是public void Student(String name,int age)传进来的name,就近原则
    		//this.age指代的是当前正在初始化的对象中的String age;
    		this.age = age;
    	}	
    }
    
    输出结果:
    age = age时,输出的是0,并非是正常的结果
    this.age = age时,输出的是正常的结果17
    

      原因也是因为会默认传一个this参数,用来指向当前使用这条命令的对象的地址,这样就可以正确的初始化当前对象中成员变量的值了

      注意:this不能用于static方法(学了static方法就知道为什么了)

    变量的种类

    实例变量、类变量、常量都是属于成员变量的,成员变量又被称为全局变量

    public class A{
        String id;                          //实例变量
        private String Tel;              //实例变量
        private int size;                 //实例变量
        private static String depart;             //类变量
        final String design="样式";                //常量
    }
     
    /*其中实例变量、类变量、常量都是属于成员变量的,成员变量又被称为全局变量,
    成员变量的范围比实例变量更宽泛 */               

    方法(函数)的种类

    实例方法(instance method):或叫成员方法(member method)。供实例用的方法,必须要先有实例,才能通过此实例调用实例方法。

    静态变量 / 类变量

    提问:有一群小孩在玩堆雪人,不时有新的小孩加入,请问如何知道现在有多少人在玩呢?请使用面向对象的思想,编程解决。

     1 public class Demo1
     2 {
     3     public static void main(String []args)
     4     {
     5         int total = 0;
     6         Child ch1 = new child(3,"小徐");
     7         ch1.joinGame();
     8         total++;
     9         
    10         Child ch2 = new child(4,"小白");
    11         ch2.joinGame();
    12         total++;
    13         //查看总人数的时候,只需要输入total的值就可以了
    14         //但是要求是使用面向对象的方法,课时这个total并没有封装到对象中去
    15     }
    16 }
    17 
    18 //定义kid类
    19 class Child
    20 {
    21     int age;
    22     String name;
    23     public Child(int age,String name)
    24     {
    25         this.age = age;
    26         this.name = name;
    27     }
    28     public void joinGame()
    29     {
    30         System.out.println("有一个小孩加入了");
    31     }
    32 }
    一般人的思维

    从上面的例子中可以看到,要是有一个所有对象都能操作的变量就好了,而java中确实有这个变量,叫做静态变量(也叫类变量)

    public class Demo1
    {
        public static void main(String []args)
        {
            Child ch1 = new Child(3,"小徐");
            ch1.joinGame();
            Child ch2 = new Child(4,"小白");
            ch2.joinGame();
            System.out.println("公有="+ch2.total);
            //也可以直接用类访问静态变量
            System.out.println("公有="+Child.total);
            
        }
    }
    
    //定义kid类
    class Child
    {
        int age;
        String name;
        //total是静态变量, 因此可以被任何一个对象访问
        static int total = 0;
        public Child(int age,String name)
        {
            this.age = age;
            this.name = name;
        }
        public void joinGame()
        {
            total++;        //在这里进行计数操作
            System.out.println("有一个小孩加入了");
        }
    }
    静态变量实现

    什么是:静态变量(类变量)?

      类变量是该类的所有对象的共享变量,任何一个该类的对象去访问它是,取到的都是相同的值,同样任何一个该类的对象去修改它时,修改的也是同一个变量。

    静态变量的定义语法

    访问修饰符   static  数据类型  变量名;
    

    静态变量的访问方法

    • 类名 . 静态变量名
    • 对象名 . 静态变量名  

    加深静态方法的理解的小例子

     1 public class Demo2
     2 {
     3     static int i=1;
     4     static         //静态区域块只会被执行一次
     5     {
     6         i++;
     7     }
     8     public Demo2()
     9     {
    10         i++;
    11     }
    12     
    13     public static void main(String []args)
    14     {
    15         Demo2 t1 = new Demo2();
    16         System.out.println(t1.i);
    17         Demo2 t2 = new Demo2();
    18         System.out.println(t2.i);
    19         
    20     }
    21 }
    猜猜看吧

    原理:

     1 public class Demo2
     2 {
     3     static int i=1;
     4     static         //静态区域块只会被执行一次
     5     {
     6         i++;
     7         System.out.println("静态区域块");
     8     }
     9     public Demo2()
    10     {
    11         i++;
    12         System.out.println("成员方法Demo2");
    13     }
    14     
    15     public static void main(String []args)
    16     {
    17         Demo2 t1 = new Demo2();
    18         System.out.println(t1.i);
    19         Demo2 t2 = new Demo2();
    20         System.out.println(t2.i);
    21         
    22     }
    23 }
    24 
    25 输出结果:
    26 静态区域块
    27 成员方法Demo2
    28 3
    29 成员方法Demo2
    30 4
    运行结果和原理

    不创建对象static也会执行,原理将来会讲

    public class Demo2
    {
        static int i=1;
        static         //静态区域块只会被执行一次
        {
            i++;
            System.out.println("静态区域块");
        }
        public Demo2()
        {
            i++;
            System.out.println("成员方法Demo2");
        }
        
        public static void main(String []args)
        {
        }
    }
    
    输出结果:
    D:myJavaDemoDay3>java Demo2
    静态区域块
    static

    静态方法(类方法)

    小例子:

    public class Demo3
    {
    	public static void main(String []args)
    	{
    		//创建一个学生
    		Stu stu1=new Stu(29,"aa",340);
    		Stu stu2 = new Stu(29,"aa",290);
    		System.out.println(stu2.getTotalFee());
    		//此时这个语法是有歧义的,感觉输出的是stu2的学费,但是输出的是所有学生的费用		
    	}
    }
    
    class Stu
    {
    	int age;
    	String name;
    	int fee;
    	static int totalFee;
    	
    	public Stu(int age,String name,int fee)
    	{
    		this.age = age;
    		this.name = name;
    		totalFee+=fee;
    	}
    	public int getTotalFee()
    	{
    		return totalFee;
    	}
    }

    使用静态方法

    java中有一个规则,静态变量原则用静态方法去访问和操作,约定俗成的。并且

    • 静态方法中不能对非静态变量操作
    • 但普通的成员方法可以操作静态变量,
    • 静态变量都可以被操作,非静态方法不能被静态方法操作
     1 public class Demo3
     2 {
     3     public static void main(String []args)
     4     {
     5         //创建一个学生
     6         Stu stu1=new Stu(29,"aa",340);
     7         Stu stu2 = new Stu(29,"aa",290);
     8         //可以直接使用Stu类名来访问这个静态方法
     9         System.out.println(Stu.getTotalFee());
    10         
    11     }
    12 }
    13 
    14 class Stu
    15 {
    16     int age;
    17     String name;
    18     int fee;
    19     static int totalFee;
    20     
    21     public Stu(int age,String name,int fee)
    22     {
    23         this.age = age;
    24         this.name = name;
    25         totalFee+=fee;
    26     }
    27     public static int getTotalFee()  //区别就是这条语句中多了一个static
    28     {
    29         return totalFee;
    30     }
    31 }
    静态方法(函数)

    什么时候使用静态方法?

    如果有一个方法(函数)需要让所有的对象去共享的时候,就可以设计成为静态方法

    静态方法的语法

    访问修饰符  static  数据返回类型  方法名 ()
    {
                //语句;
    }
    
    
    //注意静态方法中不能访问非静态变量,例如: 成员属性
    

    使用方法

    类名 . 静态方法名
    对象名 . 静态方法名
    

    类变量与实例变量的区别

    静态变量(类变量)
    int a;
    String name;
    
    实例变量
    int static a;
    String static name;
    
    • 加上static称为静态变量或类变量 ,否则称为实例变量
    • 类变量是与类相关的,公共的属性
    • 实例变量是属于每个对象个体的属性
    • 类变量可以通过 类名.类变量名 直接访问  

    静态方法(类方法)与实例方法的区别

    静态方法(类方法)
    public static int getTotalFee()  
    	{
    		return totalFee;
    	}
    
    实例方法
    public int getTotalFee()
    	{
    		return totalFee;
    	}
    
    • 类方法属于与类相关的,公共的方法  
    •  实例方法属于每个对象个体的方法
    • 类方法可以通过  类名.类方法名  直接访问

    四大特征——抽象、封装、继承、多态

    一般是说java有三大特征,即封装、继承、多态。但有人也会把抽象算进去,如顺平

    抽象

       我们前面在定义一个类的时候,实际上就是把一类事物共有的属性和行为提取出来,形成一个物理模型(模板)。这种研究问题的方法称为抽象。

    封装

    封装就是把抽象出的数据和对数据的操作封装在一起,数据被保护在内部,程序的其它部分只有通过被授权的操作(成员方法),才能对数据进行操作。

    就像电视机一样,电路板被保护在内部,我们不能直接操作电路板,但是我们可以通过电视机上的按钮来的操作电路板,从而达到我们的目的。

    访问控制修饰符

    小例子:访问公有的成员变量

     1 public class Demo4
     2 {
     3     public static void main(String []args)
     4     {
     5         Clerk clerk1 = new Clerk("小花",24,4567.6f);
     6         System.out.println("名字是"+clerk1.name);
     7         
     8     }
     9 }
    10 
    11 class Clerk
    12 {
    13     public String name;        //public共有的
    14     private int age;        //private私有的
    15     private float salary;
    16     
    17     public Clerk(String name,int age,float sal)
    18     {
    19         this.name = name;
    20         this.age = age;
    21         this.salary = sal;
    22     }
    23 }
    24 
    25 输出结果:
    26 名字是小花
    公有

    但访问私有的成员变量时,会报错

     1 public class Demo4
     2 {
     3     public static void main(String []args)
     4     {
     5         Clerk clerk1 = new Clerk("小花",24,4567.6f);
     6         System.out.println("名字是"+clerk1.name);
     7         
     8     }
     9 }
    10 
    11 class Clerk
    12 {
    13     public String name;        //public共有的
    14     private int age;        //private私有的
    15     private float salary;
    16     
    17     public Clerk(String name,int age,float sal)
    18     {
    19         this.name = name;
    20         this.age = age;
    21         this.salary = sal;
    22     }
    23 }
    24 
    25 报错信息:
    26 Demo4.java:11: 错误: salary 在 Clerk 中是 private 访问控制
    27                 System.out.println("薪水是"+clerk1.salary);
    28                                                ^
    29 1 个错误
    私有

    通过成员方法去控制和访问私有的属性

     1 public class Demo4
     2 {
     3     public static void main(String []args)
     4     {
     5         Clerk clerk1 = new Clerk("小花",24,4567.6f);
     6         System.out.println("薪水是"+clerk1.getSal());
     7         
     8     }
     9 }
    10 
    11 class Clerk
    12 {
    13     public String name;        //public共有的
    14     private int age;        //private私有的
    15     private float salary;
    16     
    17     public Clerk(String name,int age,float sal)
    18     {
    19         this.name = name;
    20         this.age = age;
    21         this.salary = sal;
    22     }
    23     //通过一个成员方法去控制和访问私有的属性
    24     public float getSal()
    25     {
    26         return this.salary;
    27     }
    28 }
    29 
    30 输出结果:
    31 薪水是4567.6
    通过公开的成员方法访问私有的属性

    因为成员方法是公开的(public),可以被使用。

    就像我们使用电视机的时候不能通过操作电路板来换台、调节音量,但是我们可以通过操作电视机给我们提供的按钮来进行换台、调节音量的操作。电视机上的按钮就相当于成员方法。

    • 厂商不让我们操作电路板,但是让我们操作按钮来间接操作电路板。
    • 类不让我们访问私有的属性,但是让我们使用成员方法来访问私有属性。

    Java提供四种访问控制修饰符号 控制 方法和变量 的访问权限

    • 公开级别:用 pulic 修饰,对外公开
    • 受保护级别:用 protected 修饰,对子类和同一个包中的类公开
    • 默认级别:没有修饰符号,像同一个包的类公开
    • 私有级别:用 private 修饰,只有类本身可以访问,不对外空开

    从包开始,就不用记事本写程序了,改成用eclipse了

    包的必要性?

     有这样的一种情况,小白定义了一个类取名为Dog,赛拉也定义了一个类取名为Dog,然后他们俩就打起来了。我们使用myeclipse来模拟一下这种情况

       

    小徐此时站了起来,说:“你们是傻吗?不知道包的作用!”

    .代表再分一层

    包的作用

    1. 区分相同名字的类
    2. 当类很多时,可以很好的管理
    3. 控制访问范围

    打包命令

    命令一般放在文件开头的地方

    package com.shunping;    //这条命令会自动生成,会自动把字节码放到com.shunping这个包中去

    命名规范

    //包名都是小写字母 , 用 . 隔开 , 比如
    com.sina.shunping  

    常用的包

    一个包下,包含很多的类,java中常用的包有:

    • java.lang.* —— 这个包是自动引入的
    • java.util.* —— 工具包
    • java.net.* —— 网络开发包
    • java.awt.* —— 窗口工具包

    引入一个包

    语法 :  import   包;
    import  java.awt.* ;
    

      我们引入一个包的主要目的是使用该包下的类

     用包来控制访问范围

     1 package com.xiaoqiang;
     2 
     3 public class Test 
     4 {
     5     public static void main(String[] args) 
     6     {
     7         Dog dog1 = new Dog();
     8 
     9                 //验证同包下的权限访问情况
    10         System.out.println(dog1.a);
    11 
    12     }
    13 
    14 }
    15 class Dog
    16 {
    17     public int a;
    18     protected String name;
    19     String color;
    20     private float price;
    21     
    22         //验证同类下的权限访问情况
    23     public void ab1()
    24     {
    25         System.out.println(this.a);
    26         
    27     }
    28 }        
    在小强的Dog类中创建四种类型的访问控制修饰符

     同类下的访问权限

    同包下的访问权限——没有私有属性的price类

    不同包下的访问权限用——用小明去访问小强中的Dog类

    在小强的包下新建一个公有的Cat类,里面的内容和Dog相同,此时小明的访问情况为

     1 package com.xiaoqiang;
     2 
     3 public class Cat 
     4 {
     5     public int a;
     6     protected String name;
     7     String color;
     8     private float price;
     9     
    10     public void ab1()
    11     {
    12         System.out.println(this.a);
    13         
    14     }    
    15 }
    小强下的公有Cat类

    权限访问情况为——只能访问公有类

    如果我就是想访问其它的属性呢?

    ——这时就要用到封装的思想,用公有的成员方法去访问私有属性

     1 package com.xiaoqiang;
     2 
     3 public class Cat 
     4 {
     5     public int a;
     6     protected String name;
     7     String color;
     8     private float price;
     9     
    10     //提供一个访问name的成员方法
    11     public String getName()
    12     {
    13         return this.name;
    14         
    15     }
    16     
    17     
    18 }
    在Cat类中提供一个访问name属性的成员方法

    继承

     为什么有继承?

    小例子:我们定义小学生,中学生,大学生类

     1 public class Demo 
     2 {
     3     public static void main(String[] args) 
     4     {
     5     }
     6 
     7 }
     8 
     9 //小学生类
    10 class Pupil
    11 {
    12     //定义成员属性
    13     private int age;
    14     private String name;
    15     private float fee;
    16     
    17     //交费
    18     public void pay(float fee)
    19     {
    20         this.fee = fee;
    21     }
    22 }
    23 
    24 //中学生类
    25 class MiddleStu
    26 {
    27     //定义成员属性
    28     private int age;
    29     private String name;
    30     private float fee;
    31     
    32     //交费
    33     public void pay(float fee)
    34     {
    35         this.fee = fee*0.8f;
    36     }
    37 }
    38 
    39 //大学生类
    40 class ColStu
    41 {
    42     //定义成员属性
    43     private int age;
    44     private String name;
    45     private float fee;
    46     
    47     //交费
    48     public void pay(float fee)
    49     {
    50         this.fee = fee*0.1f;
    51     }
    52 }
    类中成员属性重复现象

    继承就可以很好的解决代码重复问题,让我们的编程更加靠近人类的思维。

    当多个类中存在相同的属性(变量)和方法时,可以从这些类中抽象出父类,在父类中定义这些相同的属性和方法。这样所有的子类不需要重新定义这些属性和方法,只需要通过extends语句来把父类的这些属性和方法继承过来就行。

     1 public class Demo 
     2 {
     3     public static void main(String[] args) 
     4     {
     5     }
     6 
     7 }
     8 //将学生的共有属性抽象出来, 做一个父类
     9 class Student
    10 {
    11     public int age;
    12     public String name;
    13     public float fee;
    14     
    15 }
    16 //小学生类
    17 class Pupil extends Student{
    18     //交费
    19     public void pay(float fee)
    20     {
    21         this.fee = fee;
    22     }
    23 }
    24 //中学生类
    25 class MiddleStu extends Student{    
    26     //交费
    27     public void pay(float fee)
    28     {
    29         this.fee = fee*0.8f;
    30     }
    31 }
    32 //大学生类
    33 class ColStu extends Student{
    34     //交费
    35     public void pay(float fee)
    36     {
    37         this.fee = fee*0.1f;
    38     }
    39 }
    简单的继承例子

    继承的语法

    class  子类  extends  父类 ;
    //这样子类就会自动拥有父类定义的某些属性和方法,有些东西是继承不了的
    

    深入探讨——父类的哪些属性(变量)、方法被子类继承了

    父类: 
    {
    	public int a;
    	protected int b;
    	int c;
    	private int d;
    
    	public int getA(){}
    	protected int getB(){}
    	int getC(){}
    	private int getD(){}	
    }
        ————————————继承————————————
    子类: 
    {
    	public int a;
    	protected int b;
    	int c;
    
    	public int getA(){}
    	protected int getB(){}
    	int getC(){}
    }
    

      可以看出只有private修饰符的属性和方法不能被子类继承,所以不希望子类继承的属性和方法,只需要把那个属性和方法设置为private属性即可

    继承的注意事项

    1. 子类最多只能继承一个父类(指直接继承),可以通过接口进行多重继承 ,之后会讲
    2. java所有类都是Object类的子类
    3. JDK6中有202个包,3777个类、接口、异常、枚举、注释和错误,掌握150个就是大神了
    4. 在做开发的时候,强烈建议大家多查jdk帮助文档,还是不会就google
    import javax.swing.*;
    public class Demo2 extends JFrame {
    
        public static void main(String[] args) {
            Demo2 demo2 = new Demo2();
            
    
        }
        public Demo2()
        {
            this.setVisible(true);
            this.setSize(200 , 200);
        }
    
    }
    案例:利用继承调用出一个windows框框来

    如果不使用继承的话,需要调用一些复杂的命令

    方法重载

    在多态前要先了解一下方法重载(overload)和方法覆盖(override)

    思考一下:编写一个名为Abc的类,能返回两个整数中较大的一个

    • 若果是接收两个float型的数,返回较大数
    • 如果是接收散了int型的数,返回最大数
     1 public class Demo3 {
     2     public static void main(String[] args) {
     3         Abc test1 = new Abc();
     4         System.out.println(test1.getMax(23, 78));
     5     }
     6 
     7 }
     8 
     9 class Abc
    10 {
    11     public int getMax(int i,int j)
    12     {
    13         if(i>j)
    14         {
    15             return i;
    16         }
    17         else
    18         {
    19             return j;
    20         }
    21     }
    22 }
    返回两个整数中较大的数
     1 public class Demo3 {
     2     public static void main(String[] args) {
     3         Abc test1 = new Abc();
     4         Abc test2 = new Abc();
     5         System.out.println(test1.getMax(23, 78));
     6         System.out.println(test1.getMaxFloat(9.8f, 12.2f));
     7     }
     8 
     9 }
    10 
    11 class Abc
    12 {
    13     public int getMax(int i,int j)
    14     {
    15         if(i>j)
    16         {
    17             return i;
    18         }
    19         else
    20         {
    21             return j;
    22         }
    23     }
    24     public float getMaxFloat(float a,float b)
    25     {
    26         if(a>b)
    27         {
    28             return a;
    29         }
    30         else
    31         {
    32             return b;
    33         }
    34     }
    35 }
    返回两个小数中较大的一个

    可以看出我们是又专门加一个,比较小数的成员方法,有没有方法用一个方法来进行比较呢?

    这个时候有可以利用方法重载的特性——可以定义重名的两个成员方法,让编译器自己选择用哪个?

     1 package com.xiaohui;
     2 /*
     3  * 作者:我聊啊
     4  * 时间:2018.9.11
     5  * 功能:了解方法重载
     6  */
     7 public class Demo3 {
     8     public static void main(String[] args) {
     9         Abc test1 = new Abc();
    10         Abc test2 = new Abc();
    11         System.out.println(test1.getMax(23, 78));
    12         System.out.println(test1.getMax(9.8f, 12.2f));
    13     }
    14 
    15 }
    16 
    17 class Abc
    18 {
    19     public int getMax(int i,int j)
    20     {
    21         if(i>j)
    22         {
    23             return i;
    24         }
    25         else
    26         {
    27             return j;
    28         }
    29     }
    30     public float getMax(float a,float b)
    31     {
    32         if(a>b)
    33         {
    34             return a;
    35         }
    36         else
    37         {
    38             return b;
    39         }
    40     }
    41 }
    方法重载

    方法重载的概念

      简单地说:方法重载就是在类的同一种功能的多种实现方式,到底使用哪种方式,取决于调用者给出的参数。

    注意事项

    1. 方法名一定相同
    2. 方法的参数类型,个数,顺序至少有一项不同——(顺序:(int a , double b)改成(double a , int b))
    3. 返回类型也可以不相同,但是如果只有返回类型不一样,是不能够构重载的
    4. 方法的访问控制修饰符可以不同,如果只是修饰符不同,也是不能够构成重载的

    方法的覆盖(重写)

    既然子类可以继承父类的属性和方法,这样可以提高代码的复用性,这个很好,可是问题来了!!

    假设我要写三个类——猫、狗、猪,显然这三个都是动物,他们之间一定存在着相同的特点。根据类的抽象特征,我们可以把他们的相同点提取出来,形成一个父类Animal,然后继承。

    但是问题来了,动物都会叫,但是叫声是不一样的,怎样解决子类和父类方法的异同!

    这是就体现出了方法覆盖(重写)的特性了

     1 public class Demo4 
     2 {
     3     public static void main(String[] args) {
     4     Cat cat1 = new Cat();
     5     cat1.cry();
     6     
     7     Dog dog1 = new Dog();
     8     dog1.cry();
     9     }
    10 
    11 }
    12 
    13 class Animal
    14 {
    15     int age;
    16     String name;
    17     //动物都会叫
    18     public void cry()
    19     {
    20         System.out.println("我是动物,不知道怎么叫");
    21     }
    22 }
    23 class Cat extends Animal
    24 {
    25     //覆盖了父类的方法
    26     public void cry()
    27     {
    28         System.out.println("喵喵喵");
    29     }
    30 }
    31 
    32 class Dog extends Animal
    33 {
    34     //覆盖了父类的方法
    35     public void cry()
    36     {
    37         System.out.println("汪汪汪");
    38     }
    39 }
    方法覆盖——喵喵喵&汪汪汪

    方法重写的核心思想:子类的某些方法和父类不一样,需要覆盖掉父类的方法

    方法覆盖的概念

    简单的说:方法覆盖就是子类有一个方法,和父类的某个方法的名称、返回类型、参数一样,那么我们就说子类的这个方法覆盖了父类的那个方法。

    注意事项

    1. 子类的方法的返回类型,参数,方法名称要和父类方法的返回类型完全一致,否则编译会出错
    2. 子类方法不能缩小父类方法的访问权限,换句话说子类的权限可以比父类高

    多态

    所谓多态,就是指一个引用(类型)在不同情况下的多种状态。也可以这样理解:多态是指通过指向父类的指针,来调用在不同子类中实现的方法

    案例

     1 public class Demo6 
     2 {
     3     public static void main(String[] args) 
     4     {
     5         //多态
     6         Animal an;//创建了一个Animal类引用变量,Animal类引用就是以后可以用来指向Animal对象的对象引用
     7         an =new Cat();    //让这个动物的引用指向了猫这个实例(对象)
     8         an.cry();
     9         an = new Dog();
    10         //以Dog类为模板,在堆空间里创建一个Dog类对象,简称为Dog对象
    11         an.cry();
    12         //an这个引用会自动判断引用是那种类型的
    13     }
    14 }
    15 //动物类
    16 class Animal
    17 {
    18     String name;
    19     int age;
    20     public String getName() {
    21         return name;
    22     }
    23     public void setName(String name) {
    24         this.name = name;
    25     }
    26     public int getAge() {
    27         return age;
    28     }
    29     public void setAge(int age) {
    30         this.age = age;
    31     }
    32     
    33     //动物会叫
    34     public void cry()
    35     {
    36         System.out.println("不知道怎么叫");
    37     }
    38     
    39 }
    40 class Cat extends Animal
    41 {
    42     //猫自己叫
    43     public void cry()
    44     {
    45         System.out.println("喵喵喵");
    46     }
    47 }
    48 class Dog extends Animal
    49 {
    50     //狗自己叫
    51     public void cry()
    52     {
    53         System.out.println("汪汪汪");
    54     }
    55 }
    56 
    57 输出结果:
    58 喵喵喵
    59 汪汪汪
    多态

      如果没有这个特性,狗要叫就要创建一个狗的引用,猫要叫就要创建一个猫的引用,动物再多一点就会不方便管理。当然多态也能调用孙子类的方法。

     

     1 package com.xiaohui;
     2 
     3 public class Demo7 
     4 {
     5     public static void main(String[] args) 
     6     {
     7         Master master = new Master();
     8         master.feed(new Dog(), new Bone());
     9         master.feed(new Cat(),new Fish());
    10         //我想要他喂那种动物就喂那种懂我,我想喂他吃什么就吃什么
    11         //
    12     }
    13 
    14 }
    15 //主人类
    16 class Master
    17 {
    18     //给动物喂食物,使用多态,方法就可以用一个
    19     public void feed(Animal an,Food f)
    20     {
    21         an.eat();
    22         f.showName();
    23     }
    24 }
    25 
    26 class Food
    27 {
    28     String name;
    29     public void showName()
    30     {
    31         
    32     }
    33 }
    34 class Fish extends Food
    35 {
    36     public void showName()
    37     {
    38         System.out.println("鱼");
    39     }
    40 }
    41 class Bone extends Food
    42 {
    43     public void showName()
    44     {
    45         System.out.println("骨头");
    46     }
    47 }
    48 //动物类
    49 class Animal
    50 {
    51     String name;
    52     int age;
    53     //动物会吃
    54     public void  eat()
    55     {
    56         System.out.println("不知道吃什么");
    57     }
    58 }
    59 
    60 class Cat extends Animal
    61 {
    62     //猫进食
    63     public void eat()
    64     {
    65         System.out.println("猫爱吃鱼");
    66     }
    67 }
    68 
    69 class Dog extends Animal
    70 {
    71     //狗进食
    72     public void eat()
    73     {
    74         System.out.println("狗爱吃骨头");
    75     }
    76 }
    想喂猫喂猫,想喂狗喂狗

      如果Food类和Animal类下的子类有许多的话,Master类中的方法是无需改变的,只需要输入对应的动物和事物就可以了。否则我们想要狗吃骨头和猫吃鱼就要用这么多的代码来写

                    Dog dog1 = new Dog();
    		dog1.eat();
    		Bone bone1 = new Bone();
    		bone1.showName();
    
    		Cat cat1 = new Cat();
    		cat1.eat();
    		Fish fish1 = new Fish();
    		fish1.showName();    
    

    引用的注意事项:

    1. Java允许父类的引用变量引用它的子类的对象(对象)
      Animal animal = new Cat()
      

      这种转换是自动完成的  

    2. 类型转换还有一些具体的细节要求,之后会进一步学医,比如子类能不能转换成父类,有什么要求等等...  
  • 相关阅读:
    sql 查询多列 小于某值
    C#读取EXCEL 并输出到文本框
    字典
    MVC 接收文件
    C# DataTable 转 json
    MVC 返回json数据
    C# 获得指定路径扩展名 , 去除扩展名
    C# 分割URL地址
    sql语句参数化问题
    VC++学习之网络编程中的套接字
  • 原文地址:https://www.cnblogs.com/houzhaohui/p/9609559.html
Copyright © 2011-2022 走看看