面向对象(一)

107 阅读7分钟
1、面向对象/面向过程
  • 【人把大象装进冰箱】
  1. 面向过程:强调的是功能行为,以函数为最小单位,考虑怎么做。

    • ①打开冰箱门
    • ②抬起大象,装进冰箱
    • ③关闭冰箱门
  2. 面向对象:强调具备了功能的对象,以类/对象为最小单位,考虑谁来做。

    人{
        打开(冰箱){
            冰箱.开门();
        }
        抬起(大象){
            大象.进入();
        }
        关闭(冰箱){
            冰箱.关门();
        }
        
    }
    冰箱{
        开门(){}
        关门(){}
    }
    大象{
        进入(冰箱){}
    }
    
  • 面向对象三大特征
    • 封装性
    • 继承性
    • 多态性

2、类和对象
  • 类(Class):是对一类事物的描述,是抽象的,概念上的定义。

  • 对象(Object):实际存在的该类事物的每个个体,所以也称为实例(instance)

  • 万事万物皆对象:

    • 在Java语言范畴中,我们都将功能、结构等封装到类中,通过类的实例化,来调用具体的功能结构。
      • Scanner、String等
      • 文件:File
      • 网络资源:URL
    • 涉及到Java语言与前端Html、后端的数据库交互时,前后端的结构在Java层面交互时,都体现为类、对象。

3、属性/方法
  1. 属性(Field):对应类中的成员变量
  2. 方法(Method):对应类中的成员方法(函数)

4、类和对象的创建
  1. 创建类,设计类的成员

  2. 创建类的对象

  3. 通过【对象.属性】或【对象.方法】调用对象的结构

    public class PersonTest {
        public static void main(String[] args) {
            Person per = new Person();
            per.name = "张三";
            per.age = 20;
            per.sex = "男";
            System.out.println(per.name + "、" + per.age + "、" + per.sex);
            per.eat();
            per.sleep();
            per.speak("中文");
    
            /*
            张三、20、男
            人可以吃...
            人可以睡...
            人可以说:中文
            */
        }
    }
    class Person{
        String name;
        int age;
        String sex;
    
        public void eat(){
            System.out.println("人可以吃...");
        }
        public void sleep(){
            System.out.println("人可以睡...");
        }
        public void speak(String language){
            System.out.println("人可以说:"+language);
        }
    }
    

5、对象内存解析
  • 如果创建了一个类的多个对象,则每个对象都独立地拥有一套类的属性(非static的),意味着:如果修改一个对象的属性a,则不会影响另外一个对象属性a的值。
  • 编译完源程序以后,生成一个或多个字节码文件;使用JVM中类的加载器和解释器对生成的字节码文件进行解释运行。意味着,需要将字节码文件对应的类加载到内存中,涉及到内存解析。
  • 堆栈的概念:

  • 范例:观察以下代码及其内存解析:
public class PersonTest {
    public static void main(String[] args) {
        Person p1 = new Person();
        p1.name = "Tom";
        p1.isMale = true;
        System.out.println(p1.name);//Tom
        p1.eat();//人可以吃...
        p1.sleep();//人可以睡...
        p1.talk("Chinese");//人可以说:Chinese
        //*************************************************
        Person p2 = new Person();
        System.out.println(p2.name);//null
        System.out.println(p2.isMale);//false
        //*************************************************
        //将p1变量保存的对象地址赋给p3,导致p1和p3指向了堆空间中同一个对象实体。
        Person p3 = p1;
        System.out.println(p3.name);//Tom
        p3.age = 10;
        System.out.println(p1.age);//10
    }
}
class Person{
    String name;
    int age = 1;
    boolean isMale;

    public void eat(){
        System.out.println("人可以吃...");
    }
    public void sleep(){
        System.out.println("人可以睡...");
    }
    public void talk(String language){
        System.out.println("人可以说:"+language);
    }
}


6、属性(成员变量)与局部变量的对比
  1. 相同点:

    1. 定义变量的格式相同:【数据类型 变量名 = 变量值;】
    2. 先声明,后使用;
    3. 变量都有其对应的作用域;
  2. 不同点:

    1. 在类中声明的位置的不同:

      • 属性:直接定义在类的一对{}内;

      • 局部变量:声明在方法内、方法形参、代码块内、构造器形参、构造器内部的变量;

    2. 关于权限修饰符的不同:

      • 属性:可以在声明时,使用权限修饰符(常用的:private、public、缺省[什么都不加]、protected)指明其权限【封装性】;

      • 局部变量:不可以使用权限修饰符;

    3. 默认初始化值的情况:

      • 属性:类的属性,根据其类型,都有默认初始化值;

        • 【整型:byte、short、int、long】:0
        • 【浮点型:float、double】:0.0
        • 【字符型:char】:0或\u0000
        • 【布尔型:boolean】:false
        • 【引用数据类型:类、数组、接口】:null
      • 局部变量:没有默认初始化值,意味着在调用局部变量之前一定要显示赋值;特别地:形参在调用时赋值即可;

    4. 在内存中加载的位置

      • 属性:加载到对空间中(非static);
      • 局部变量:加载到栈空间中;

7、方法
  • 方法:描述类应该具有的功能

  • 分类:

  • 方法的声明:

    /*
    权限修饰符 返回值类型 方法名(形参列表){
    	方法体
    }
    
    以上的是一个方法一定有的结构组成
    使用static、final、abstract...类似的关键字修饰的方法,这些关键字也会出现在方法结构中,但是不一定必须存在,视情况而定
    */
    public void eat(){}
    public void sleep(int hour){}
    public String getName(){
        return "";
    }
    public String getNation(String nation){
        return "";
    }
    
  • 说明:

    1. 权限修饰符【与属性类似,属于封装性的内容】

    2. 返回值:

      • 有返回值:如果方法有返回值,则必须在方法声明时指定返回值类型;同时需要使用return关键字来返回指定类型的变量或常量;

      • 没有返回值:如果方法没有返回值,则使用void表示;通常,没有返回值的方法中就没有必要使用return了,但是一定要使用的话,则表示结束此方法的意思,使用方法如下:

        public void eat(){
            System.out.println("客户吃饭");
            return;
            //return之后不可以声明表达式
            //System.out.println();           
        }
        
    3. 方法名:属于标识符,遵循标识符的规则和规范,【见名知意】

    4. 形参列表:方法可以声明0个、1个、多个形参;

    5. return关键字的使用:

      • 使用范围:使用在方法体中;
      • 作用:【1】:结束方法;【2】针对有返回值类型的方法,返回该方法需要的数据;
      • 注意点:return关键字后面不可以声明执行语句;
  • 方法使用中的注意点:

    1. 方法中可以调用当前类的属性或方法,特殊的:方法A中调用方法A【递归方法】;
    2. 方法中不可以定义方法;

8、匿名对象
  • 创建的对象没有显式的赋给一个变量名

  • 只能调用一次

  • 范例代码:

    public class JavaDemo {
        public static void main(String[] args) {
            //匿名对象
            new Phone().price = 2000;
            System.out.println(new Phone().showPrice());//0.0
    
            //匿名对象的使用
            phoneMall mall = new phoneMall();
            mall.show(new Phone());
        }
    }
    class phoneMall{
        public void show(Phone phone){
            phone.sendEmil();
            phone.playGames();
        }
    }
    class Phone{
        double price;
    
        public void sendEmil(){
            System.out.println("发送邮件");
        }
        public void playGames(){
            System.out.println("玩游戏");
        }
        public double showPrice(){
            return price;
        }
    }
    

9、练习——类的设计

public class PersonTest {
    public static void main(String[] args) {
        Person p1 = new Person();

        p1.name = "Tom";
        p1.age = 20;
        p1.sex = 1;

        p1.study();//studying
        p1.showAge();//age:20
        p1.addAge(2);
        int newAge = p1.age;
        System.out.println(newAge);//22

        //***************************************************
        Person p2 = new Person();
        p2.showAge();//0
        p2.addAge(10);
        p2.showAge();//10
    }
}
class Person{
    String name;
    int age;
    /**
     * 文档注释
     * sex:1表示男性
     * sex:0表示女性
     */
    int sex;

    public void study(){
        System.out.println("studying");
    }
    public void showAge(){
        System.out.println("age:"+age);
    }
    public int addAge(int i){
        age += i;
        return age;
    }
}

范例:创建类Circle计算圆的面积

public class CircleTest {
    public static void main(String[] args) {
        Circle c = new Circle();
        c.radius = 2.1;
        double area = c.findArea();
        System.out.println(area);//13.854423602330987
    }
}
class Circle{
    double radius;

    public double findArea(){
        double area = Math.PI*radius*radius;
        return area;
    }
}

10、练习——方法声明

public class Exer3Test {
    public static void main(String[] args) {
        Exer3Test e = new Exer3Test();
        e.method();
    }
    public void method(){
        for (int i = 0 ; i < 10 ; i++){
            for (int j = 0 ; j < 8 ; j++){
                System.out.print("*");
            }
            System.out.println();
        }
    }
}
public class Exer3Test {
    public static void main(String[] args) {
        Exer3Test e = new Exer3Test();
        System.out.println("矩形面积为:"+e.method());
    }
    public int method(){
        for (int i = 0 ; i < 10 ; i++){
            for (int j = 0 ; j < 8 ; j++){
                System.out.print("*");
            }
            System.out.println();
        }
        return 10*8;
    }
}
public class Exer3Test {
    public static void main(String[] args) {
        Exer3Test e = new Exer3Test();
        System.out.println("矩形面积为:"+e.method(5,5));
    }
    public int method(int m , int n){
        for (int i = 0 ; i < m ; i++){
            for (int j = 0 ; j < n ; j++){
                System.out.print("*");
            }
            System.out.println();
        }
        return m*n;
    }
}

11、练习——对象数组

public class StudentTest {
    public static void main(String[] args) {
        //创建一个学生对象数组
        Student[] stus = new Student[20];
        //实例化类对象
        StudentTest studentTest = new StudentTest();
        //为学生对象数组赋值
        studentTest.assignment(stus);
        //遍历该数组
        studentTest.print(stus);
        System.out.println("-------------------------------------------");
        //打印出3年级学生信息
        studentTest.printState(stus,3);
        System.out.println("-------------------------------------------");
        //使用冒泡排序,并遍历数组
        studentTest.sort(stus);
        studentTest.print(stus);
    }
    //为学生对象数组赋值
    public void assignment(Student[] stus){
        for (int i = 0 ; i < stus.length ; i++){
            stus[i] = new Student();

            stus[i].number = (i+1);//学号为1-20
            stus[i].state = (int)(Math.random()*(6-1+1)+1);//1-6年级
            stus[i].score = (int)(Math.random()*(100-0+1));//分数为0-100
        }
    }
    //打印出3年级学生信息
    public void printState(Student[] stus , int state){
        for (int i = 0 ; i < stus.length ; i++){
            if (stus[i].state == 3){
                System.out.println(stus[i].info());
            }
        }
    }
    //冒泡排序
    public void sort(Student[] stus){
        for (int i = 0 ; i < stus.length-1 ; i++){
            for (int j = 0 ; j < stus.length-1-i ; j++){
                //如果需要换序,交换的是数组的元素:Student对象!!!
                if (stus[j].score > stus[j+1].score){
                    Student temp = stus[j];
                    stus[j] = stus[j+1];
                    stus[j+1] = temp;
                }
            }
        }
    }
    //遍历学生对象数组并输出
    public void print(Student[] stus){
        for (int i = 0 ; i < stus.length ; i++){
            System.out.println(stus[i].info());
        }
    }
}
class Student{
    int number;//学号
    int state;//年级
    int score;//成绩

    public String info(){
        return "学号:"+number+"、年级:"+state+"、成绩:"+score;
    }
}