第7章 面向对象编程(基础部分)

7.1  类与对象 oop

         问题:编写一个程序,输入猫名字,显示该猫的名字,年龄,颜色

        现有技术:单独定义变量、数组;缺点:不利于数据管理,效率低

       中包含对象(属性 + 行为),如将人类中的属性和行为实例化就是一个具体的人

        类与对象的区别与联系

        1.类是抽象的,概念的,代表一类事物,如人类,类是数据类型

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

        对象在内存中存在形式!!!

         属性/成员变量/字段

         成员变量 = 属性 = field 字段,可以是基本数据类型,也可以是引用类型(对象、数组)

        属性定义语法同变量,默认值同数组

public class Exercise {
    public static void main(String[] args]{
        
        //创建对象,p为对象名
        Person p = new Person();

        //访问属性
        p.age;
        p.name;    
        p.sal;

        //调用方法
        p.speak();
        int returnRes = p.getSum(10,20);
        System.out.println(returnRes);
    
    }
}

class Person { //创建类 Person

    //属性(成员变量、字段)
    int age;
    String name;
    double sal;

    //行为(方法)
    public void speak(){  //访问修饰符+返回类型(void表示无需返回)+方法名+(形参列表)
        System.out.println("我是一个好人");//方法体
    }

    public int getSum(int num1, int num2) {
        int res = num1 + num2;
        return res;
    }

}

        类和对象的内存分配机制

         栈:一般存放基本数据类型(局部变量)

        堆:存放对象(Cat cat , 数组等)

        方法区:常量池(常量,如字符串),类加载信息(只加载一次)

        顺序:先加载类信息-->堆中分配空间,有基本数据类型的指向方法区的常量池-->地址赋给对象名(栈),指向对象

7.2  成员方法

        基本介绍

         在某些情况下,我们需要定义成员方法(简称方法)。比如人类:除了有一些属性(年龄、姓名等),还有一些行为(说话、跑步、学习等),这些行为就需要成员方法来完成。

        方法的调用机制原理!!!

        成员方法好处:提高代码的复用性;可以将实现的细节封装起来,然后供其他用户调用即可

        定义:

访问修饰符  返回类型  方法名(形参列表){
    语句;
    return 返回值;//不是必须,如没有返回值时(void)不用 
}

        注意事项和使用细节 

        访问修饰符:不写则默认(public、protected、private、默认)

        返回数据类型:

        1.一个方法最多有一个返回值

        2.返回类型可以为任意类型,包含基本类型和引用类型(数组、对象)

        3.如果方法要求有返回类型,则方法体中最后的执行语句必须为return值;且返回值类型必须和return的值类型一致或兼容

        4.如果方法是void,则方法体中可以没有return语句,或者只写return;

        方法名:小驼峰命名、见名知义

        行参列表:

        1.一个方法可以有0个参数,也可以有多个参数,逗号隔开

        2.参数类型可以为任意类型,包含基本类型和引用类型

        3.调用带参数的方法时,一定对应着形参列表传入相同类型或兼容类型的参数

        4.方法定义时的参数成为形式参数,简称形参;方法调用时的传入参数称为实际参数,简称实参,实参和形参的类型要一致或兼容、个数、顺序必须一致!

        方法体:完成功能的具体语句,可以输入、输出、变量、运算、分支、循环、方法调用,但不能在定义方法

        方法调用细节

        1.同一个类中的方法调用:直接调用即可。方法名();

        2.跨类中的方法a类调用b类方法:需要通过对象名调用。及在a类的方法中创建b类,在调用

        3.跨类的方法调用与方法的访问修饰符有关

7.3  成员方法传参机制(非常重要)

        基本数据类型的传参机制

        基本数据类型,传递的是值(值拷贝),形参的任何改变不影响实参

public class Exercise {
    public static void main(String[] args){

        int a = 10;
        int b = 20;
        T t = new T();
        t.swap(a, b);

        System.out.println("main方法" + a + b);//a=10; b=20
    }
}

class T {
    public void swap(int a, int b) {
        System.out.println("交换前" + a + b); // a=10;b=20
        int temp = a;
        a = b;
        b = temp;
        System.out.println("交换后" + a + b);//a=20;b=10
    }
}

       引用数据类型的传参机制

        引用类型传递的是地址(传递也是值,但是是值的地址),可以通过形参影响实参

/*
案例:
B类中编写方法test100,接收数组,在方法中修改数组,原数组变化吗?  会
B类中编写方法test200,接收Person(age,sal)对象,在方法中修改该对象属性,原对象是否变化,  会
*/
public class Exercise {
    public static void main(String[] args){
        B b = new B();
        int[] arr = {1, 2, 3};
        b.test100(arr);
        System.out.println("main的arr数组");
        for(int i = 0, i < arr.length; i++){
             System.out.println(arr[i] + "  ");
        }
         System.out.println();

        Person p = new Person();
        p.name = "jack";
        p.age = 10;
        b.test200(p);
        //如果执行 p = null; 下面结果为 10 
        //如果执行 p = new Person();下面结果为 10
        System.out.println("main的p.age =" + p.age); //10000
    
    }
}

class Person {
    String name;
    int age;

}

class B {

    public void test100(int[] arr){
        arr[0] = 200;//修改数组
        System.out.println("test100的arr数组");
        for(int i = 0, i < arr.length; i++){
             System.out.println(arr[i] + "  ");
        }
         System.out.println();
    
    } 

    public void test200(Person p){
        //p.age = 10000;//修改对象属性
        p = new Person();
        p.name = "tom";
        p.age = 99;
        //思考
        //p = null;
    }


}

​​​​​​​

         成员方法返回类型是引用类型(数组、对象)实例

public class Exercise {
    public static void main(String[] args){
        Person p = new Person();
        p.name = "milan";
        p.age = 100;
        MyTools tools = new MyTools;
        Person p2 = tools.copyPerson(p);
        //到此p和p2是Person对象,但是是两个独立的对象,属性相同

    }
}

 class Person {
    String name;
    int age;

}

class MyTools {

    public Person copyPerson(Person p) {
        Person p2 = new Person();
        p2.name = p.name;
        p2.age = p.age;
        return p2;
    }
}

7.4  方法递归调用(非常非常重要) factorial

        递归就是方法自己调用自己,每次调用时传入不同的变量

        阶乘问题

public class Exercise {
    public static void main(String[] args) {
        T t1 = new T();
        int res = t1.factorial(5);
        System.out.println("5的阶乘为" + res);
    }
}

class T {

    public int factorial(int n) {
        if(n == 1) {
            return 1;
        }else {
            return factorial(n - 1) * n;
        }
    }


}

        递归重要规则

        1.执行一个方法时,就创建一个新的受保护的独立栈空间

        2.方法的局部变量时独立的,不会互相影响,比如n

        3.如果方法中使用的是引用类型(数组、对象),就会共享该引用类型的数据

        4.递归必须向退出递归的条件逼近,否则就是无限递归

        5.当一个方法执行完毕,或者遇到return,就会返回,遵守谁调用,就将结果返回给谁,同时当方法执行完毕或者返回时,该方法也就执行完毕 

        递归调用实例--迷宫问题

public class MiGong {
    public static void main(String[] args){
        //创建迷宫,1表示障碍物,0表示可以走
        int[][] map = new int[8][7];
        for(int i = 0; i < 7; i++) {
            int[0][i] = 1;
            int[7][i] = 1;
        }
        for(int i = 0; i < 8; i++) {
            int[i][0] = 1;
            int[i][6] = 1;
        }
        map[3][1] = 1;
        map[3][2] = 1;
        //遍历数组,形成迷宫
        for(int i = 0; i < map.length; i++) {
            for(int j = 0; j < map[i].length; j++) {
                System.out.println(map[i][j] + " ");
            }
            System.out.println();
        }
        //找路
        T t1 = new T();
        t1.findWay(map, 1, 1);
        //重新遍历数组,找到出路
         for(int i = 0; i < map.length; i++) {
            for(int j = 0; j < map[i].length; j++) {
                System.out.println(map[i][j] + " ");
            }
            System.out.println();
        }



    }
}

class T {
    //创建找路方法findWay;规定2表示可以走,3表示走过;起始位置(1,1),目标位置(6,5)
    //找路策略为下-右-上-左;当目标位置mao[6][5] = 2;则找到通路
    public boolean findWay(int[][] map, int i, int j) {
        if(map[6][5] == 2) {
            return true;
        }else {
            if(map[i][j] == 0) {
                map[i][j] = 2;
                if(findWay(map, i + 1, j){
                    return true;
                    }else if(findWay(map, i, j + 1){
                        return true;
                    }else if(findWay(map, i - 1, j){
                        return true;
                    }else if(findWay(map, i, j - 1){
                        return true;  
                    }else {
                        map[i][j] = 3;
                        return false;
                    }
            }else {
                return false;
            }

    }

}

7.5  方法重载 overload

        java中允许同一个类中,多个同名方法的存在,但要求 形参列表不一致!方法重载减轻了起名和记名的麻烦。

        注意事项和使用细节

        1.方法名必须相同;2.行参列表必须不同(参数名无要求);3.返回类型 无要求

7.6  可变参数

        java允许将同一个类中多个同名同功能但参数个数不同的方法,封装成一个方法。通过可变参数实现。

访问修饰符   返回类型   方法名(数据类型... 形参名){

    }

public class Exercise {
    public static void main(String[] args){
        HspMethod m = new HspMethod();
        System.out.println(1,5,100);
        System.out.println(1,5,100,333,55,67);
    }
}

class HspMethod {

    public int sum(int... nums){
        int res = 0;
        for(int i = 0; i < nums.length; i++) {
            res += nums[i];
        }
        return res;
    }

}

        注意事项和使用细节

        1.可变参数的实参可以为0个或任意多个

        2.可变参数的实参可以为数组

        3.可变参数的本质就是数组

        4.可变参数可以和普通类型的参数一起放在形参列表,但必须保证可变参数在最后

        5.一个形参列表只能出现一个可变参数

7.7  作用域 varscope

        基本使用

        1.在java编程中,主要的变量就是属性(成员变量)和局部变量

        2.我们说的局部变量一般是指在成员方法中定义的变量

        3.java中作用域的分类:1)全局变量:也就是属性,作用域为整个类体;2)局部变量:也就是除了属性之外的其他变量,作用域为定义它的代码块中

        4.全局变量(属性)可以不赋值,直接使用,因为有默认值。局部变量必须赋值后,才能使用,因为没有默认值。

        注意事项和细节

        1.属性和局部变量可以重名,访问时遵循就近原则

        2.在同一个作用域中,比如在同一个成员方法中,两个局部变量,不能重名

        3.属性生命周期长,伴随着对象的创建而创建,销毁而销毁。局部变量声明周期短,伴随着它的代码块的执行而创建,结束而销毁,即在一次方法调用过程中。

        4.作用域范围不同:全局变量可以被本类或其他类使用(通过对象调用,第一种是在类的方法中新建类实现跨类访问;第二种是在类的方法中传入对象调用);局部变量只能在本类中对应的方法中使用

        5.修饰符不同:全局变量可以加修饰符;局部变量不行

7.8  构造方法/构造器 constructor

        需求:前面创建对象时,是先创建在赋值。若要求创建时就赋值,利用构造器

【修饰符】 方法名(形参列表){

        方法体;

}

定义:构造方法又叫构造器,是类的一种特殊的方法,它的主要作用是完成对新对象的初始化。

         说明:1.构造器的修饰符可以默认,也可以是其余3种

                     2.构造器没有返回值,也不能写void

                     3.方法名 和 类名字必须一样

                     4.参数列表 和 成员方法规则一样

                     5.构造器调用由系统完成

class Person {

        String name;

        Int age;

        public Person(String pName, int pAge){  //构造器

                name = pName;

                age = pAge;

        }

}

        注意事项和使用细节

        1.构造器重载:一个类可以定义多个不同的构造器

        2.构造器是完成对象的初始化,并不是创建对象

        3.在创建对象时,系统会自动调用该类的构造方法

        4.如果没有定义构造器,系统会自动给类生成一个默认的无参构造器(默认构造器)

        5.一旦定义了自己的构造器,默认的构造器就覆盖了,也就不能使用默认的无参构造器,除非显示的定义一下

//如Dog类中,显示定义

Dog(){

7.9  对象创建的流程分析 

        参考以前的流程分析图

7.10  this 关键字

        问题:改进构造器参数名,将pName、pAge改为name、age更好,但根据作用域原则,name的值就是null,解决方法--> this

        哪个对象调用,this就代表哪个对象

        注意事项和使用细节

        1.this关键字可以用来访问本类的属性、方法、构造器

        2.this用于区分当前类的属性和局部变量

        3.访问成员方法的语法:this.方法名(参数列表);

        4.访问构造器语法:this(参数列表);注意只能在构造器中使用,即只能在构造器中访问另外一个构造器,必须放在第一条语句

        5.this不能在类定义的外部使用,只能在类定义的方法中使用

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值