java面向对象编程

1.1.1 类与对象

一个问题?[Demo107.java]

张老太养了两只猫猫:一只名字叫小白,今年3岁,白色。还有一只叫小花,今年100岁,花色。请编写一个程序,当用户输入小猫的名字时,就显示该猫的名字,年龄,颜色。如果用户输入的小猫名错误,则显示张老太没有这只猫猫。

//用前面学习过的知识写出代码
public class Demo107{
    public static void main(String []args){
        int a=49;//输入的名字49,50
        int cat1age=3; //第一只猫
        String cat1name="小白";
        String cat1color="白色";
        int cat2age=100; //第二只猫
        String cat2name="小花";
        String cat2color="花色";
        switch(a){
        case '1':
            System.out.println(cat1age+cat1color);
            break;
        case '2':
            System.out.println(cat2age+cat2color);
            break;
        default:
            System.out.println("张老太没有这只猫!");
        }
    }
}

java语言是面向对象的

计算机语言的发展向接近人的思维方式演变

汇编语言 [面向机器]

c语言 [面向过程]

java语言 [面向对象]

类和对象的关系

把猫的特性提取出来-->猫类-->对象(实例)-->对象(实例)-->...

注意:从猫类到对象,目前有几种说法:
1、创建一个对象;
2、实例化一个对象;
3、对类实例化...以后大家听到这些说法,不要模糊。( 对象就是实例,实例就是对象)java最大的特点就是面向对象。

//定义猫类
public class Demo105{
    public static void main(String []args){
        //创建一个猫对象
        Cat cat1=new Cat();//Cat是定义的一个数据类型
        //Cat cat1;
        //cat1=new Cat();// 等同于 Cat cat1=new Cat();
        //访问属性的 对象名.属性名字
        cat1.age=3;
        cat1.name="小白";
        cat1.color="白色";

        //创建第二只猫
        Cat cat2=new Cat();
        cat2.age=100;
        cat2.name="小花";
        cat2.color="花色";  
    }
}

//java中如何定义一个类?[类名的首写字母大写]可根据程序的需要定义类
class Cat{
    //下面的就是类的成员变量/属性
    int agr;
    String name;
    String color;
    Master myMaster;
}

//引用类型,比如建个主人类
class Master{
    int age;
    String name;
    String address;
}

类和对象的区别和联系

1、类是抽象的,概念的,代表一类事物,比如人类,猫类..

2、对象是具体的,实际的,代表一个具体事物

3、类对象的模板,对象是类的一个个体,实例

-- 如何定义类

一个全面的类定义比较复杂,如:

package 包名;
class 类名 extends 父类 implements
接口名{
 成员变量;
 构造方法;
 成员方法;
}

要透彻的掌握类,必须要了解类的构成

class 类名{ ----> 待定...

  成员变量;

}

1. -- 类的成员变量 :

成员变量是类的一个组成部分,一般是基本数据类型,也可是引用类型。比如我们前面定义猫类的int age 就是成员变量。

2. 对象 -- 如何创建对象 :

创建一个对象有两种方法

1、先声明再创建

1 、对象声明:类名 对象名

2 、对象创建:对象名=new 类名()

2、一步到位法

类名 对象名=new 类名()

对象--如何访问(使用)对象的成员变量

对象名 . 变量名; // 简单先这样理解,以后加下控制符此表达就不准确了。

  • 对象总是存在内存中的

一个小思考题[Demo.105.java]

为了让大家加深印象,我们定义一个人类(Person)(包括名字、年龄)。用一步到位法去创建一个对象

我们看看下面一段代码:

System.out.printlin(b.age);

Person a=new Person(); →  请问:b.age究竟是多少?

a.age=10;

a.name="小明";

Person b;

b=a;
  • 对象总是存在内存中的

一个小思考题[Demo106.java]

在明白对象是如何在内存中存在后,请大家再看看下面的思考题,请问会输出什么信息?

Person1 a=new Person1();

a.age=10;

a.name="小明";

Person1 b;

b=a;

System.out.println(b.name);//输出“小明”

b.age=200;

System.out.println(a.age);//输出a.age为200
  • 重点也是难点

类--成员方法的初步介绍

在某些情况下,我们要需要定义成员方法。比如人类:除了有一些属性外(成员变量表示的年龄、姓名...),我们人类还有一些行为比如:可以说话、跑步..,通过学习,我们人类还可以做算术题。这时就要用成员方法才能完成。现在要求对Person类完善:

1、添加speak成员方法,输入出:我是一个好人

2、添加jisuan成员方法,可以计算从1+..+1000的结果

3、修改jisuan成员方法,该方法可以接收一个数n,计算从1+..+n的结果

4、添加add成员方法,可以计算两个数的和

3. -- 类的成员方法 ( 成员函数 ) 定义 :

成员方法也叫成员函数,这里希望大家不要被两个名词搞晕了。

public 返回数据类型 方法名(参数列表)
    {
        语句;//方法(函数)主体
    }

1、参数列表:表示成员函数输入

2、数据类型(返回类型):表示成员函数输出

3、函数主体:表示为了实现某一功能代码块

//类的调用及方法调用[Demo108.java]
public class Demo108{
    public static void main(String []args){
    Person p1=new Person();
    p1.speak();//调用speak方法
    p1.jiSuan();//调用计算方法
    p1.jiSuan(200);//调用可以传入参数的计算方法
    p1.add(12,10);//调用两个数的和
    
    int res=p1.add2(23,34);//调用两个数的和并返回值到res中
    System.out.println("res返回值是:"+res);
    System.out.println("num1+num2+num3="+p1.add3(2,2.3f,4.5f));//返回类型一定要一致否则报错。
}
}
//定义名字的几个方法:
//1、驼峰法 如myCry;2、下划线法my_cry
//方法名在有不同参数的情况下可以使用同一个方法名,即有参数和没参数的方法可以同名
class Person{ //请注意类名首写字母应为大写如Person为类名 
    int age;
    String name;
    //1、可以输出我是好人方法
    public void speak(){  //请注意方法名的首写字母应为小写如speak为方法名
        System.out.println("我是一个好人");
    }
    //2、可以计算1+..+1000的方法
    public void jiSuan(){
        int result=0;
        for(int i=1;i<=1000;i++){
            result=result+i;
        }
    System.out.println("1+..+1000结果是"+result);
    }
    //3、带参数的成员方法,可以输入n值并计算1+..+n
    public void jiSuan(int n){
        int result=0;
        for(int i=1;i<=n;i++){
            result+=i;
        }
        System.out.println("1+..+n结果是"+result);
    }
    //4、计算两个数的和
    public void add(int num1,int num2){
        int result=0;   //与下面一句等同于return num1+num2;
        result=num1+num2;
        System.out.println("num1+num2="+result);
    }
    //5、计算两个数的和,并将结果返回给主调(调用它的)函数
    //注意:返回类型和返回结果的类型要一致
    //注意:在调用某个成员方法的时候,给出的具体数值的个数
    //和类型要相匹配。
    public int add2(int num1,int num2){
        return num1+num2;
    }
    //6、计算两个float数的和,并将结果返给主调函数
    public float add3(int num1,float num2,float num3){
        return num1+num2+num3;
    }
}

-- 类的成员方法(函数)--如何理解

如何理解方法这个概念,给大家举个通俗的示例:

程序员调用方法:给方法必要的输入,方法返回结果。

类的成员方法-- 声明 :

public int test(int a);/*方法声明*/

这句话的作用是声明该方法,声明的格式为:

访问修饰符 数据类型 函数名(参数列表);

在给Person类添加add方法的例题中,我们看到的关键字return ,它的功能是把表达式的值返回的值返回给主调函数的方法。

return 表达式;

类的成员方法(函数)--特别说明

1、方法的参数列表可以是多个

案例:在Person类中编写一个成员方法,从键盘输入三个数,返回最大的那个数。

参数列表可以是多个,并且数据类型可以是任意的类型int float double char..

    访问修饰符 返回数据类型 函数名(参数列表){
        语句; //函数主体
    }

2、方法可以没有返回值

案例:编写一个函数,从控制台输入一个整数打印出对应的金字塔。

返回类型可以是任意的数据类型(int,float,double,char..)也可以没有返回值void表示没有返回值

    访问修饰符 返回数据类型 函数名(形参列表){
        语句; //函数主体
    }

类的成员方法(函数)--小练习

案例:编写一个成员函数,从键盘输入一个整数(1-9),打印出对应的乘法表[Demo110.java]

//实例键盘输入打印乘法表[Demo110.java]
import java.io.*;
public class Demo110{
    public static void main(String []args){
        Cfb jiu=new Cfb();
            jiu.cf();
    }
}
class Cfb{
    public void cf(){
        try{
        //输入流,从键盘接收数
        InputStreamReader isr=new InputStreamReader(System.in);
        BufferedReader br=new BufferedReader(isr);
        //给出提示
        System.out.println("请输入1-9,按0退出:");
        //从控制台读取一行数据
        String a1=br.readLine();
        //把String转为int
        int num1=Integer.decode(a1);
            for(int i=1;i<=num1;i++){
                for(int j=1;j<=i;j++){
                    System.out.print(i+"×"+j+"="+(i*j)+"\t");
                }
                System.out.println();           
            }
        }catch(Exception e){
          e.printStackTrace();
         }
    }
}

案例:编写函数,使给定的一个二维数组(3×3)转置

类定义的完善

在介绍了成员方法后,我们类的定义就可以完善一步:

class 类名{ class 类名{  待定

成员变量; →  成员变量; →        

}  成员方法;

   }

小结:1.先设计类;2.然后根据类创建对象。

小练习:

1、设计计算机类,要求如下:[Demo109.java]

属性:品牌(Brand)、颜色(Color)、cpu型号(CPU)、内存容量(Memory)、硬盘大小(Harddisk)、价格(Price)、工作状态(Work)

方法:打开(Open)、关闭(Close)、休眠(Sleep)

创建一个计算机对象,调用打开,关闭方法

//计算机类与对象的代码
import java.io.*;//加载IO流包
public class Demo109{
    public static void main(String []args){
        Computer Pc=new Computer();
            Pc.Brand="品牌";
            Pc.Color="颜色";
            Pc.Cpu="Cpu型号";
            Pc.Memory="内存容量";
            Pc.Hd="硬盘容量";
            Pc.Price="价格";
            Pc.Work="工作状态";
            try{
            //输入流,从键盘接收数
            InputStreamReader isr=new InputStreamReader(System.in);
            BufferedReader br=new BufferedReader(isr);
            //给出提示
            System.out.println("请输入0-9控制机器");
            //从控制台读取一行数据
            String a1=br.readLine();
            //把String转为float
            float num1=Float.parseFloat(a1);
            if(num1==0){Pc.open();}
            else if(num1==1){Pc.close();}
            else if(num1==2){Pc.sleep();}
            else if(num1==3){System.out.println(Pc.Brand);}
            else if(num1==4){System.out.println(Pc.Color);}
            else if(num1==5){System.out.println(Pc.Cpu);}
            else if(num1==6){System.out.println(Pc.Memory);}
            else if(num1==7){System.out.println(Pc.Hd);}
            else if(num1==8){System.out.println(Pc.Price);}
            else if(num1==9){System.out.println(Pc.Work);}
            else {System.out.println("输入错误!");} 
            }catch(Exception e){ 
            e.printStackTrace();
            }
    }
}

class Computer{
    String Brand;
    String Color;
    String Cpu;
    String Memory;
    String Hd;
    String Price;
    String Work;
    public void open(){
        System.out.println("开机");
    }
    public void close(){
        System.out.println("关机");
    }
    public void sleep(){
        System.out.println("休眠");
    }
}

1、 采用面向对象思想设计超级马里奥游戏人物


1.1.2 构造方法(函数)

类的构造方法介绍

什么是构造方法呢?在回答这个问题之前,我们来看一个需求:前面我们在创建人类的对象时,是先把一个对象创建好后,再给他的年龄和姓名属性赋值,如果现在我要求,在创建人类的对象时,就直接指定这个对象的年龄和姓名,该怎么做?

你可以在定义类的时候,定义一个构造方法即可。

构造方法是类的一种特殊的方法,它的主要作用是完成对新对象的初始化。它有几个特点:

1、方法名和类名相同

2、没有返回值

3、在创建一个类的新对象时,系统会自动的调用该类的构造方法完成对新对象的初始化。

特别说明:

一个类可以定义多个不同的构造方法。

//例人类构造方法[Demo111.java]
public class Demo111{
    public static void main(String []args){
        Person p1=new Person(12,"顺平");//给予不同的初始值,调用的构造方法不同,构造方法虽同名,但系统会根据初始值来选定构造方法。
    }
}
//定义一个人类
class Person{
    int age;
    String name;
    //默认构造方法
    public Person(){
    }
    //构造方法的主要用处是:初始化你的成员属性(变量)
    //构造方法
    public Person(int age,String name){
        System.out.println("我是构造1");
        age=age;
        name=name;
    }
    //构造方法2
    public Person(String name){
        System.out.println("我是构造2");
        name=name;
    }
}

类的默认构造方法

有些同志可能会问?亲爱的老师,我们在没有学习构造函数前不是也可以创建对象吗?

是这样的,如果程序员没有定义构造方法,系统会自动生成一个默认构造方法。比如Person类Person (){};

当创建一个Person对象时Person per1=new Person();默认的构造函数就会被自动调用。

类的构造方法小结:

1 、构造方法名和类名相同;

2 、构造方法没有返回值;

3 、主要作用是完成对新对象的初始化;

4 、在创建新对象时,系统自动的调用该类的构造方法;

5 、一个类可以有多个构造方法;

6 、每个类都有一个默认的构造方法。

类定义的改进

在提出构造方法后,我们类的定义就应该更加完善了:

class 类名{ class 类名{ class 类名{

成员变量; 成员变量; 成员变量;

} →  成员方法; →  构造方法; →  待定..

 } 成员方法

 }

1.1.3 this

一个问题?

请大家看一段代码:(Demo112.java)

重点:this是属于一个对象,不属于类的。

java虚拟机会给每个对象分配this,代表当前对象。坦白的讲,要明白this不是件容易的事

注意事项:this不能在类定义的外部使用,只能在类定义的方法中使用

/*
    this的必要性
*/
public class Demo112{
    public static void main(String []args){
        Dog dog1=new Dog(2,"大黄");
        Person p1=new Person(dog1,23,"郭德纲");
        Person p2=new Person(dog1,24,"刘谦");
        p1.showInfo();  
        p1.dog.showInfo();
    }
}
//定义一个人类
class Person{
    //成员变量
    int age;
    String name;
    Dog dog;//引用类型
    public Person(Dog dog,int age,String name){
        //可读性不好
        //age=age;
        //name=name;
        this.age=age; //this.age指this代词指定是成员变量age
        this.name=name; //this.name指this代词指定是成员变量name
        this.dog=dog;
    }
    //显示人名字
    public void showInfo(){
        System.out.println("人名是:"+this.name);
    }
}

class Dog{
    int age;
    String name;
    public Dog(int age,String name){
        this.age=age;
        this.name=name;
    }
    //显示狗名
    public void showInfo(){
        System.out.println("狗名叫"+this.name);
    }
}

类变量--提出问题?

提出问题的主要目的就是让大家思考解决之道。

public class Demo113{
    public static void main(String []args){
    /*  int total=0;
        Child ch1=new Child(3,"妞妞");
        ch1.joinGame();
        total++;
        Child ch2=new Child(4,"小小");
        ch2.joinGame();
        total++; 
    */
        Child ch1=new Child(3,"妞妞");
        ch1.joinGame();
        Child ch2=new Child(4,"小小");
        ch2.joinGame();
        Child ch3=new Child(5,"大大");
        ch3.joinGame();
        System.out.println("共有="+Child.total);
    }
}
//定义小孩类
class Child{
    int age;
    String name;
    //static公共函数,total是静态变量,因此它可以被任何一个对象访问
    static int total=0; 
    public Child(int age,String name){
        this.age=age;
        this.name=name;
    }
    public void joinGame(){
        total++;
        System.out.println("有一个小孩加入了");
    }
}


1.1.4 类变量、类方法

什么是类变量?

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

如何定义类变量?

定义语法:

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

如何访问类变量?

类名 . 类变量名 或者 对象名 . 类变量名

//类变量的程序演示[Demo114.java]
public class Demo114{
    static int i=1;
    static{
        //该静态区域块只被执行一次
        i++;
        System.out.println("执行一次");
    }
    public Demo114(){  //建立Demo114()构造函数
        System.out.println("执行二次");
        i++;
    }
    public static void main(String []args){
        Demo114 t1=new Demo114();  //创建t1对象实例并调用Demo114函数
        System.out.println(t1.i);

        Demo114 t2=new Demo114();
        System.out.println(t2.i);
    }
}

什么是类方法,为什么有类方法?

类方法是属于所有对象实例的,其形式如下:

访问修饰符 static 数据返回类型 方法名(){}

注意:类方法中不能访问非静态变量(类变量)。

使用:类名 . 类方法名 或者 对象名 . 类方法名

重点static静态的方法可以访问static静态变量,不能访问非静态变量(类变量)

非静态方法可以访问非静态变量(类变量)同时也可以访问static静态变量。

//统计总学费的程序代码,加深static静态的方法由静态变量的访问[Demo115.java]
public class Demo115{
    public static void main(String []args){
        //创建一个学生
        Stu stu1=new Stu(29,"aa",340);
        Stu stu2=new Stu(29,"aa",240);
        System.out.println(Stu.getTotalFee());
    }
}

//学生类
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;
    }
    //返回总学费[这是一个类方法(静态方法)]
    //java中规则:类变量原则上用类方法去访问或操作
    public static int getTotalFee(){
        return totalFee;
    }
}

类变量小结

1、什么时候需要用类变量

案例[Demo115.java]:定义学生类,统计学生共交多少钱?

用类变量,属于公共的属性

2、类变量与实例变量区别:

加上static称为类变量或静态变量,否则称为实例变量

类变量是与类相关的,公共的属性

实例变量属于每个对象个体的属性

类变量可以通过 [类名 . 类变量名] 直接访问

类方法小结

1、什么时候需要用类方法

案例[Demo115.java]:定义学生类,统计学生共交多少钱?

类方法属于与类相关的,公共的方法

实例方法属于每个对象个体的方法

类方法可以通过 [类名 . 类方法名] 直接访问


java 面向对象编程的四大特征

抽象/封装/继承/多态

1 抽象 :

1、简单理解

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

封装--什么是封装

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

封装--访问控制修饰符

电视机的开关,对音量,颜色,频道的控制是公开的,谁都可以操作,但是对机箱后盖,主机板的操作却不是公开的,一般是由专业维修人员来玩。那么java中如何实现这种类似的控制呢?不能随便查看人的年龄,工资等隐私[Demo116.java]

//封装案例[Demo116.java]
public class Demo116{
    public static void main(String []args){
        //创建一个职员
        Clerk clerk1=new Clerk("小花",24,4567.6f);
        System.out.println("名字是"+clerk1.name+"薪水"+clerk1.getSal());
    }
}
//职员
class Clerk{
    public String name;
    //private私有的,public公有的
    private int age;
    private float salary;

    public Clerk(String name,int age,float sal){
        this.name=name;
        this.age=age;
        this.salary=sal;
    }
    //通过一个成员方法去控制和访问私有的属性
    public float getSal(){
        return this.salary;
    }
}

2. 封装 -- 访问控制修饰符 :

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

1 、公开级别:用public修饰,对外公开

2 、受保护级别:用protected修饰,对子类和同一个包中的类公开

3 、默认级别:没有修饰符号,向同一个包的类公开

4 、私有级别:用private修饰,只有类本身可以访问,不对外公开

包--必要性

问题的提出,请看下面的一个场景[eclipse]

现在有两个程序员共同开发一个java项目,程序员xiaoming希望定义一个类取名Dog,程序员xiaoqiang也想定义一个类也叫Dog。两个程序员为此还吵了起来,怎么办?

-- 三大作用

1、区分相同名字的类

2、当类很多时,可以很好的管理类

3、控制访问范围

-- 换包命令

package com. 自定义名字;

注意:打包命令一般放在文件开始处。

包--命名规范

小写字母 比如 com.sina.shunping

包--常用的包

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

java.lang.* 包 自动引入 java.util.* 工具包

java.net.* 包 网络开发包 java.awt.* 包 窗口工具包

包--如何引入包

语法:import 包;

比如import java.awt.*;

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

定义类的改进

在提出包后,我们类的定义就更加完善了:

class 类名{ class 类名{ class类名{ package包名; 待定..

成员变量; →  成员变量; →  成员变量; →  class 类名{  →

} 成员方法; 构造方法; 成员变量;

 } 成员方法; 构造方法;

 } 成员方法;

 }

3继承--为什么有?

//功能:说明继承的重要性
package com.abc;//包名
public class Demo117 {
    public static void main(String[] args) {
        Pupil p1=new Pupil();
        p1.printName();
    }
}

//将学生的共有属性提取,做一个父类
class Stu{
    //定义成员属性
    protected int age;
    public String name;
    public float fee;
    private String job;//私有将不被继承
    
    //编程中,如果你不希望子类继承某个属性或方法
    //则将其声明为private即可
    public void printName(){
        System.out.println("名字"+this.name);
    }
}

//小学生类
class Pupil extends Stu{
    //交学费
    public void pay(float fee){
        this.fee=fee;
    }
}
//幼儿
class Pre extends Pupil{
    //交学费
    public void pay(float fee){
        this.fee=fee*1.5f;
    }
}
//中学生类
class MiddleStu extends Stu{
    //交学费
    public void pay(float fee){
        this.fee=fee*0.8f;
    }
}
//大学生类
class ColStu extends Stu{
    //交学费
    public void pay(float fee){
        this.fee=fee*0.1f;
    }
}

继承 -- 解决之道

继承可以解决代码复用,让我们的编程更加靠近人类思维。当多个类存在相同的属性(变量)和方法时,可以从这些类中抽象出父类(比如刚才的Student),在父类中定义这些相同的属性和方法,所有的子类不需要重新定义这些属性和方法,只需要通过extends语句来声明继承父类:

语法:class 子类 extends 父类

这样,子类就会自动拥有父类定义的某些属性和方法。

继承--深入讨论

1、父类的哪些属性(变量)、方法被子类继承了?并不是父类的所有属性、方法都可以被子类继承

父类 子类

public 属性; public 属性;

protected 属性; 继承 protected 属性;

private 属性; → 属性;

属性;

public 方法; public 方法;

protected 方法; protected 方法;

private 方法; 方法;

方法;

2、结论

从图可以看出,父类的public修饰符的属性和方法;protected修饰符的属性和方法;默认修饰符属性和方法被子类继承了,父类的private修饰符的属性和方法不能被子类继承。

继承--注意事项

1、子类最多只能继承一个父类(指直接继承)

2、java所有类都是Object类的子类 (所有的子类都可以逐级继承,例:爷->父->子->孙)

3、JDK6中有202个包3777个类、接口、异常、枚举、注释和错误

4、在做开发的时候,强烈建议大家多查jdk帮助文档

5、在使用类时,实在不知道怎么办,多使用搜索引擎

4. 定义类的改进 :

在提出包后,我们类的定义就更加完善了:

class 类名{ class 类名{ class类名{ package包名;   

成员变量; →  成员变量; →  成员变量; →  class 类名{ 

} 成员方法; 构造方法; 成员变量;

 } 成员方法; 构造方法;

 } 成员方法;

 }  ↓

↓←←←←←←←←←←←←←←←←←←←←←←←←←

package 包名;

class 类名 extends 父类{ 待定

  成员变量; → ....

  构造方法;

  成员方法;

}

1.1.5 方法重载(overload)和方法覆盖(override)

1 方法重载 (overload)

按顺序,我们应该讲解多态,但是在讲解多态前,我们必须讲解方法重载和方法覆盖(override)。

请编写一个类(Abc),编写方法可以接收两个整数,返回两个数中较大的数[Demo119.java]

//方法重载(overload)getMax
public class Demo119{
    public static void main(String []args){
        Abc2 abc1=new Abc2();
        System.out.println(abc1.getMax(12,14));
        System.out.println(abc1.getMax(24f,20f));
    }
}

class Abc2{
    //返回较大的整数
    public int getMax(int i,int j){
        if(i>j){
            return i;
        }else{
            return j;
         }
    }
    public float getMax(float a,float b){
        if(a>b){
            return a;
        }else{
            return b;
         }
    }
    //如果只是返回类型不一样,能否构成重载?不能够构成重载
/*  public double getMax(float d,double c){
        if(c>d){
            return c;
        }else{
            return d;
         }
    }
    //如果只是控制访问修饰符不同,能否构成重载?不能够构成重载
    protected float getMax(float c,float d){
        if(c>d){
            return c;
        }else{
            return d;
         }
    }*/
}

方法重载(overload) 概念

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

注意事项:

1、方法名相同

2、方法的参数类型,个数,顺序至少有一项不同

3、方法返回类型可以不同(只是返回类型不一样,不能构成重载)

4、方法的修饰符可以不同(只是控制访问修饰符不同,不能构成重载)

2 方法覆盖 (override)

既然子类可以继承父类的属性和方法,这样可以提高代码的复用性,这个很好,可是问题来了,假设现在我要求大家写三个类猫猫,狗狗,猪猪。我们知道这三个东东都是动物,动物必然存在相同的特点。根据类的抽象特征,我们可以把它们的相同点提取出来,形成一个父类,然后继承。

//子类方法覆盖父类方法[Demo120.java]
public class Demo120{
    public static void main(String []args){
        //创建一只猫
        Cat cat1=new Cat();
            cat1.cry();
        Dog dog1=new Dog();
            dog1.cry();
    }
}
//动物类
class Animal{
    int age;
    String name;
    //都会叫
    public void cry(){
        System.out.println("我是动物,不知道怎么叫");
    }

}
//猫猫类
class Cat extends Animal{
    //覆盖父类方法
    public void cry(){
        System.out.println("猫猫叫!");
    }
}
//狗狗类
class Dog extends Animal{
    //覆盖父类方法
    public void cry(){
        System.out.println("汪汪叫!");
    }
}

方法覆盖(override)概念

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

注意事项:

方法覆盖有很多条件,有些书上说的比较细,总的讲有两点一定注意:

1、子类的方法的返回类型,参数,方法名称,要和父类的返回类型,参数,方法名称完全一样,否则编译出错。

2、子类方法不能缩小父类方法的访问权限。

===============================================================================

作业:上机实习题目

1、Josephu问题(丢手帕问题)

Josephu问题为:设编号为1,2,...n的n个人围坐一圈,约定编号为k(1<=k<=n)的人从1开始报数,数到m的那个人出列,它的下一位又从1开始报数,数到m的那个人又出列,依次类推,直到所有人出列为止,由此产生一个出队编号的序列。

提示:用一个不带头结点的循环链表来处理Josephu问题:先构成一个有n个结点的单循环链表,然后由k结点起从1开始计数,计到m时,对应结点的人从链表中删除,然后再从被删除结点的下一个结点又从1开始计数,直到最后一个结点从链表中删除算法结束。

//Josephu问题(丢手帕问题)
//使用单向链表
public class Demo121 {
    public static void main(String[] args) {
        CycLink cyclink=new CycLink();
        cyclink.setLen(5);//链表长度
        cyclink.createLink();
        cyclink.setK(2);//从第几个人开始数
        cyclink.setM(2);//数几下
        cyclink.show();
        cyclink.play();
    }
}

class Child{
    int no;
    Child nextChild=null;
    public Child(int no){
        //给一个编号
        this.no=no;
    }
}

//单向环形链表
class CycLink{
    //先定义一个指向链表第一个小孩的引用
    //指向第一个小孩的引用,不能动
    Child firstChild=null;
    Child temp=null;
    int len=0;//表示共有多少个小孩
    int k=0;
    int m=0;
    //设置m数几下
    public void setM(int m){
        this.m=m;
    }
    //设置环形链表大小
    public void setLen(int len){
        this.len=len;
    }
    //设置从第几个人开始数数
    public void setK(int k){
        this.k=k;
    }
    //开始play
    public void play(){
        Child temp=this.firstChild;
        //1.先找到开始数数的人
        for(int i=1;i<k;i++){
            temp=temp.nextChild;
        }
        while(this.len!=1){
            //2.数m下
            for(int j=1;j<m;j++){
                temp=temp.nextChild;
            }
            //找到要出圈的前一个小孩
            Child temp2=temp;
            while(temp2.nextChild!=temp){
                temp2=temp2.nextChild;
            }
            //3.将数到m的小孩,退出圈
            temp2.nextChild=temp.nextChild;
            //让temp指向下一个数数的小孩
            temp=temp.nextChild;
            this.len--;
        }
        //最后一个小孩
        System.out.println("最后出圈的小孩:"+temp.no);
    }
    
    //初始化单向环形链表
    public void createLink(){
        for(int i=1;i<=len;i++){
            if(i==1){
                //创建第一个小孩
                Child ch=new Child(i);
                this.firstChild=ch;
                this.temp=ch;
            }else{
                //创建最后一个小孩
                if(i==len){
                    Child ch=new Child(i);
                    temp.nextChild=ch;
                    temp=ch;
                    temp.nextChild=this.firstChild;
                }else{
                    //继续创建小孩
                    Child ch=new Child(i);
                    temp.nextChild=ch;
                    temp=ch;    
                }
            }
        }
    }
    //打印该环形链表
    public void show(){
        //定义一个跑龙套
        Child temp=this.firstChild;
        do{
            System.out.print(temp.no+" ");
            temp=temp.nextChild;
        }while(temp!=this.firstChild);
    }
}

1.1.6 四大特征

1多态-- 概念

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

实现多态有两种方式:1、继承;2、接口

多态演示[Dome122.java]

//演示继承、方法覆盖、多态
public class Demo122 {
    public static void main(String[] args) {
        //非多态演示
        Cat cat=new Cat();
        cat.cry();
        Dog dog=new Dog();
        dog.cry();
        //多态演示
        Animal an=new Cat();
        an.cry();
        an=new Dog();
        an.cry();
    }
}
//动物类
class Animal{
    String name;
    int age;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    //动物会叫
    public void cry(){
        System.out.println("不知道怎么叫");
    }
}
//创建Dog子类并继承Animal父类及覆盖cry方法
class Dog extends Animal{
    //狗叫
    public void cry(){
        System.out.println("汪汪叫");
    }
}
class Cat extends Animal{
    //猫自己叫
    public void cry(){
        System.out.println("猫猫叫");
    }
}

2 多重多态演示[Dome123.java]

//演示子类继承父类、方法覆盖、多态方法
public class Demo123 {
    public static void main(String[] args) {
        //非多态演示
        System.out.println("非多态演示:");
        Cat cat=new Cat();
        cat.cry();
        Dog dog=new Dog();
        dog.cry();
        System.out.println();       
        //多态演示
        System.out.println("多态演示:");
        Animal an=new Cat();
        an.cry();
        an=new Dog();
        an.cry();
        System.out.println();   
        //多重多态演示
        System.out.println("多重多态演示:");
        Master master=new Master();
        master.feed(new Dog(),new Bone());
        master.feed(new Cat(),new Fish());
    }
}
//主人类
class Master{
    //给动物喂食物,使用多态,只要写一个方法
    public void feed(Animal an,Food f){
        an.eat();
        f.showName();
    }
}
//食物父类
class Food{
    String name;
    public void showName(){
        System.out.println("食物");
    }
}
//食物鱼子类
class Fish extends Food{
    public void showName(){
        System.out.println("鱼");
    }
}
//食物骨头子类
class Bone extends Food{
    public void showName(){
        System.out.println("骨头");
    }
}
//动物类Animal父类
class Animal{
    String name;
    int age;
    
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    //动物会叫
    public void cry(){
        System.out.println("不知道怎么叫");
    }
    //动物吃东西
    public void eat(){
        System.out.println("不知道吃什么");
    }
}
//创建Dog子类并extends继承Animal父类及覆盖cry方法
class Dog extends Animal{
    //狗叫
    public void cry(){
        System.out.println("汪汪叫");
    }
    //狗吃东西
    public void eat(){
        System.out.println("狗爱吃骨头");
    }
}
class Cat extends Animal{
    //猫自己叫
    public void cry(){
        System.out.println("猫猫叫");
    }
    //猫吃东西
    public void eat(){
        System.out.println("猫爱吃鱼");
    }
}

3 多态 -- 注意事项:

1、java允许父类的引用变量引用它的子类的实例(对象)

Animal an=new Cat();//这种转换时自动完成的

2、关于类型转换还有一些具体的细节要求,我们在后面还要提,比如子类能不能转换成父类,有什么要求等等...


1.1.7 抽象类

1 抽象类 -- 解决之道

当父类的一些方法不能确定时,可以用abstract关键字来修饰该方法[抽象方法],用abstract来修饰该类[抽象类]。

//抽象类的必要性[Demo124.java]
public class Demo124 {
    public static void main(String[] args) {
        //Animal an=new Animal();抽象类不允许实例化
        Animal an=new Cat();
        an.cry();
        an=new Dog();
        an.cry();
    }
}
//抽象类abstract关键词
abstract class Animal{
    String name;
    int age;
    //动物会叫,使用了abstract抽象方法
    abstract public void cry();//抽象类中可以没有abstract抽象方法
    //抽象类内可以有实现方法
    public void sx(){
        System.out.println("实现方法");
    }
}
//当一个子类继承的父类是abstract抽象类的话,需要程序员把抽象类的抽象方法全部实现。
class Cat extends Animal{
    //实现父类的cry,其实类似上节学习中的子类覆盖父类
    public void cry(){
        System.out.println("猫猫叫");
    }
}
class Dog extends Animal{
    //实现父类的cry,其实类似上节学习中的子类覆盖父类
    public void cry(){
        System.out.println("汪汪叫");
    }
}

2 抽象类 -- 深入讨论

抽象类是java中一个比较重要的类。

1 、用abstract关键字来修饰一个类时,这个类就是抽象类。

2 、用abstract关键字来修饰一个方法时,这个方法就是抽象方法。

3 、abstract抽象类中的abstract抽象方法是不允许在抽象类中实现的,一旦实现就不是抽象方法和抽象类了。abstract抽象方法只能在子类中实现。

4 、抽象类中可以拥有实现方法。

5、抽象方法在编程中用的不是很多,但是在公司笔试时,却是考官比较爱问的知识点。

3 抽象类****--****注意事项

1 、抽象类不能被实例化

2 、抽象类不一定要包含abstract方法。也就是说,抽象类可以没有abstract抽象方法。

3 、一旦类包含了abstract抽象方法,则这个类必须声明为abstract抽象类。

4 、抽象方法不能有主体。

正确的抽象方法例:abstract void abc();

错语的抽象方法例:abstract void abc(){}

1.1.8 接口

1 接口 -- 为什么有?

USB插槽就是现实中的接口。

什么是接口?

接口就是给出一些没有内容的方法,封装到一起,到某个类要使用的时候,在根据具体情况把这些方法写出来。

接口的建立语法:interface 接口名 { 方法;}

语法:class 类名 implements 接口 {

方法;

变量;

}

小结:接口是更加抽象的抽象的类,抽象类里的方法可以有方法体,接口里的所有方法都没有方法体。接口体现了程序设计的多态和高内聚低偶合的设计思想。

2 接口 -- 注意事项

1、接口不能被实例化

2、接口中所有的方法都不能有主体。错误语法例:void aaa(){}←(注意不能有花括号)

接口可以看作更加抽象的抽象类。

3、一个类可以实现多个接口

4、接口中可以有变量[但变量不能用private和protected修饰]

a、接口中的变量,本质上都是static的而且是final类型的,不管你加不加static修饰

b、在java开发中,我们经常把常用的变量,定义在接口中,作为全局变量使用

访问形式:接口名 . 变量名

5、一个接口不能继承其它的类,但是可以继承别的接口

//接口的实现[Demo125.java]
//电脑,相机,u盘,手机

//usb接口
interface Usb{
    int a=1;//加不加static都是静态的,不能用private和protected修饰
    //声明了两个方法
    public void start();//接口开始工作
    public void stop();//接口停止工作
}
//编写了一个相机类,并实现了usb接口
//一个重要的原则:当一个类实现了一个接口,要求该类把这个接口的所有方法全部实现
class Camera implements Usb{
    public void start(){
        System.out.println("我是相机,开始工作了..");
    }
    public void stop(){
        System.out.println("我是相机,停止工作了..");
    }
}
//接口继承别的接口
class Base{
}
interface Tt{
}
interface Son extends Tt{
}
//编写了一个手机,并实现了usb接口
class Phone implements Usb{
    public void start(){
        System.out.println("我是手机,开始工作了..");
    }
    public void stop(){
        System.out.println("我是手机,停止工作了..");
    }
}
//计算机
class Computer{
    //开始使用usb接口
    public void useUsb(Usb usb){
        usb.start();
        usb.stop();
    }
}
public class Demo125 {
    public static void main(String[] args) {
        System.out.println(Usb.a);
        //创建 Computer
        Computer computer=new Computer();
        //创建Camera
        Camera camera1=new Camera();
        //创建Phone
        Phone phone1=new Phone();
        computer.useUsb(camera1);
        computer.useUsb(phone1);
    }
}

3 定义类的改进

有了接口,我们类的定义就更加完善了:

class 类名{ class 类名{ class类名{ package包名;   

成员变量; →  成员变量; →  成员变量; →  class 类名{ 

} 成员方法; 构造方法; 成员变量;

 } 成员方法; 构造方法;

 } 成员方法;

 }  ↓

↓←←←←←←←←←←←←←←←←←←←←←←←←←

package 包名; package 包名;

class 类名 extends 父类{ class 类名 extends 父类 implements 接口名{

  成员变量;    →  成员变量;

  构造方法; 构造方法;

  成员方法; 成员方法;

} }

4 实现接口VS继承类

java的继承是单继承,也就是一个类最多只能有一个父类,这种单继承的机制可保证类的纯洁性,比C++中的多继承机制简洁。但是不可否认,对子类功能的扩展有一定影响。所以:

1、实现接口可以看作是对继承的一种补充。(继承是层级式的,不太灵活。修改某个类就会打破继承的平衡,而接口就没有这样的麻烦,因为它只针对实现接口的类才起作用)

2、实现接口可在不打破继承关系的前提下,对某个类功能扩展,非常灵活。

//实例:建立子类并继承了父类且连接多个接口[Demo126.java]
public class Demo126 {
    public static void main(String[] args) {
        System.out.println("继承了Monkey父类");
        Monkey mo=new Monkey();
        mo.jump();
        LittleMonkey li=new LittleMonkey();
        li.swimming();
        li.fly();
    }
}
//接口Fish
interface Fish{
    public void swimming();
}
//接口Bird
interface Bird{
    public void fly();
}
//建立Monkey类
class Monkey{
    int name;
    //猴子可以跳
    public void jump(){
        System.out.println("猴子会跳!");
    }
}
//建立LittleMonkey子类并继承了Monkey父类并连接了Fish和Bird接口
class LittleMonkey extends Monkey implements Fish,Bird{
    public void swimming() {
        System.out.println("连接了Fish接口!");
    }
    public void fly() {
        System.out.println("连接了Bird接口!");
    }
}

5 用接口实现多态--案例[Demo127.java]

java中多态是个难以理解的概念,但同时又是一个非常重要的概念。java三大特性之一(继承,封装,多态),我们可以从字面上简单理解:就是一种类型的多种状态,以下通过卖小汽车的例子说明什么是多态。

//用接口实现多态
public class Demo127 {
    public static void main(String []args){
        CarShop aShop=new CarShop();
        //卖出一辆宝马
        aShop.sellCar(new BMW());
        //卖出一辆奇瑞QQ
        aShop.sellCar(new CheryQQ());
        //卖出一辆桑塔纳
        aShop.sellCar(new Santana());
        System.out.println("总收入:"+aShop.getMoney());
    }
}
//汽车接口
interface Car{
    //汽车名称
    String getName();
    //获得汽车售价
    int getPrice();
}
//宝马
class BMW implements Car{
    public String getName(){
        return "BMW";
    }
    public int getPrice(){
        return 300000;
    }
}
//奇瑞QQ
class CheryQQ implements Car{
    public String getName(){
        return "CheryQQ";
    }
    public int getPrice(){
        return 20000;
    }
}
//桑塔纳汽车
class Santana implements Car{
    public String getName(){
        return "Santana";
    }
    public int getPrice(){
        return 80000;
    }
}
//汽车出售店
class CarShop{
    //售车收入
    private int money=0;        
    //卖出一部车
    public void sellCar(Car car){
        System.out.println("车型:"+car.getName()+"单价:"+car.getPrice

());
        //增加卖出车售价的收入
        money+=car.getPrice();
    }
    //售车总收入
    public int getMoney(){
        return money;
    }
}

运行结果:

车型:BMW 单价:300000

车型:CheryQQ 单价:20000

总收入:320000

继承是多态得以实现的基础。从字面上理解,多态就是一种类型(都是Car类型)表现出多种状态(宝马汽车的名称是BMW,售价是300000;奇瑞汽车的名称是CheryQQ,售价是2000)。将一个方法调用同这个方法所属的主体(也就是对象或类)关联起来叫做绑定,分前期绑这下和后期绑定两种。下面解释一下它们的定义:

1 、前期绑定:在程序运行之前进行绑定,由编译器和连接程序实现,又叫做静态绑定。比如static方法和final方法,注意,这里也包括private方法,因为它是隐式final的。

2 、后期绑定:在运行时根据对象的类型进行绑定,由方法调用机制实现,因此又叫做动态绑定,或者运行时绑定。除了前期绑定外的所有方法都属于后期绑定。

多态就是在后期绑定这种机制上实现的。多态给我们带来的好处是消除了类之间的偶合关系,使程序更容易扩展。比如在上例中,新增加一种类型汽车的销售。只需要让新定义的类实现Car类并实现它的所有方法,而无需对原有代码做任何修改,CarShop类的sellCar(Car

car)方法就可以处理新的车型了。

新增代码如下:

java代码

//桑塔纳汽车
class Santana implements Car{
    public String getName(){
        return "Santana";
    }
    public int getPrice(){
        return 80000;
    }
}

1.1.9 final

final概念

final中文意思:最后的,最终的。

final可以修饰变量或者方法。

在某些情况下,程序员可能有以下需求:

1 、当不希望父类的某个方法被子类覆盖(override)时,可以用final关键字修饰。

2 、当不希望类的某个变量的值被修改,可以用final修饰。如果一个变量是final,则必须赋初值,否则编译出错。

3 、当不希望类被继承时,可以用final修饰。

//final方法的使用[Demo128.java]
public class Demo128 {
    public static void main(String[] args) {
        Aaa aaa=new Aaa();
        aaa.show();
        Bbb bbb=new Bbb();
        bbb.show();
    }
}
class Aaa{ 
    int a=0;//如果a不赋初值,a是0。定义类型后应赋值
    //圆周率不让修改
    //带有final修饰的变量命名时应有_下划线来区分表示。这是java程序员的标准。
    final float reate_1=3.1415926f;//使用final可以保证,需要强制不被修改的数据一定要用final锁定
    //final int b;  //使用final定义变量时一定要赋初值否则报错。
    //b=1;
    final public void sendMes(){//给成员方法用final来修饰则表示不可以被修改,不可被覆盖。
        System.out.println("发送消息");
    }
    public void show(){
        System.out.println("a="+a);
    }
}
final class Bbb extends Aaa{//定义类前加final表示该类不允许被继承
    public Bbb(){
        a++;
        //reate_1=reate+1;
    }
    /*public void sendMes(){
        System.out.println("发送消息")
    }*/
}

final-- 注意事项

1、final修饰的变量又叫常量,一般用XX_XX_XX来命名。(带下划线)

2、final修饰的变量在定义时,必须赋值,并且以后不能再赋值。

final-- 什么时候用

1、因为案例的考虑,类的某个方法不允许修改。

2、类不会被其它的类继承。

3、某些变量值是固定不变的,比如圆周率3.1415926


11997621-8a2084c8bf69c458.png
tobehero666.png
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值