面向对象基础讲解

245 阅读9分钟

面向对象

一.类与对象

  1. 基本介绍:
        //1)类是抽象的,概念的,代表一类事物,
        //2)对象是具体的,实际的。代表具体的事物,属性的载体,行为的执行者
        //3)类是对象的模板,对象是类的一个个体,对应一个实例
  2.  如何创建对象  

        //1. 直接创建:类名 对象名 = new 类名();
        //2.先声明在创建  类名 对象名;  对象名 = new ();
        // 访问属性  cat.name   对象名.属性名



实例讲解: //养猫问题
    
        //1.先把所有的猫的特性提取出来
        //2.猫类:自定义数据类型 int: java提供数据类型  如猫的年龄 大小 行为  **类就是数据类型
        //3.猫对象(具体一只猫) 100 200   ** 对象是具体的事物

   
        //定义一个猫类
        // 实例化一个猫对象
        //1.new Cat()   创建一个猫对象
        //2.Cat cat1 = new Cat();  把创建的猫对象赋给cat1
        Cat  cat1 = new Cat();
        cat1.name = "奶盖";
        cat1.age = 18;
        cat1.color = "白色";
        cat1.weight = 45;

        Cat  cat2 = new Cat();
        cat2.name = "酷盖";
        cat2.age = 18;
        cat2.color = "黑色";
        cat2.weight = 23;
        System.out.println("第一只猫的信息 " + cat1.name + "  " + cat1.age + " " + cat1.color + " " + cat1.weight);
        System.out.println("第二只猫的信息 " + cat2.name + " " + cat2.age + " " + cat2.color + " " + cat2.weight);

        class Cat{
            //属性
            String name;  //名字
            int age;      // 年龄
            String color; // 花色
            // 可以继续增加信息
            int weight;
        }
    
  类与对象内存的分配机制:
        //Java 内存的结构分析
        //1.栈:一般存放基本数据类型
        //2.堆:存放对象(Cat cat等)
        //3.方法区:常量池(字符串),类加载信息

        //简单分析:
        //2.Cat cat1 = new Cat();  把创建的猫对象赋给cat1
               Cat  cat1 = new Cat();
                cat1.name = "奶盖";
                cat1.age = 18;
                cat1.color = "白色";
        //1.先加载Cat信息
        //2.堆中分配空间,进行默认初始化
        //3.把地址给cat1.cat1指向对象
        //4.进行指定初始化
        //2.Cat cat1 = new Cat();  把创建的猫对象赋给cat1
        Cat  cat1 = new Cat();
        cat1.age = 18;
        cat2.age = 20;   地址age元素改变
        //cat2 = null;   // 不能指向地址  出现异常

二 .成员方法

 成员方法定义:
                public 返回数据类型  方法名(形参列表){
                   方法体
                            语句;
                    return 返回值;  // 如果为void没有返回值
                }
     
         // ** 编写方法的思路
        1.方法的返回类型
        2.方法的名字
        3.方法的形参
    实例引入:
     //1)添加speak 成员 输出” 酷盖是大好人“

        //1.方法创建好要去调用    2.** 先创建对象 : 调用名+ 创建名 = 对象名.+调用名  3.使用:创建名.方法名();
       ** Person p1 = new Person();// 创建对象
          p1.speak();
		输出结果:酷盖是大好人
        //2)添加一个cal02的成员 计算1+ 2 + ... + n
        p1.cal02( 1000);//在形参列表中输入n的值

     
class Person{
   
    //1.public 表示方法公开
    //2.void 表示没有返回值
    //3.speak():speak 表示方法名 ():表示形参列表
    public void  speak(){
        System.out.println("酷盖是大好人");
        
         public void getSum(int a,int b){

        int sum = 0;
        sum = a + b;
        System.out.println("两数之和 = " + sum);

    }
    }
    
        // ** 方法的调用机制
        //首先建立一个main栈  person p1 = new Person() 指向堆里面的对象
        //接着执行int return res = p1.getSum() 语句 这时会在栈里创建一个新的独立空间接着分别给a,b赋值  返回res
        // 最后res 指向 int return res = p1.getSum(a,b)
        //执行完会将独立空间栈释放

        // 方法调用小结:
        //1.当程序找到方法时会开辟一个新的独立栈空间
        //2.当程序执行完毕,或者执行到return语句时就会返回
        //3.返回到调用方法的地方
        //4.返回后执行下面的代码
        //5.当main(栈)执行完毕整个程序退出。


   方法的使用细节:
        //1.一个方法只能返回一个值 (可以利用数组返回多个值)
        Person tool = new Person();
        int resArr[] = tool.getSumAndSub(23, 22);
        System.out.println("和= " + resArr[0] + "\n" + "差 = " + resArr[1]);
class Person{
  public int [] getSumAndSub(int a,int b){

        int resArr[] = new int [2] ;
        resArr[0] = a + b;
        resArr[1] = a - b;

        return resArr;
  }

    }
        //2. 返回类型可以为任意类型,基本类型 引用类型  具体见上
        //3.如果方法中需要返回值 需要保证返回数据类型与return数据类型相同或兼容  && 形参也一样
        //public int arr(){
        double a  = 1.1 * 5;
        return a;  // 不行 double不能到int
        public double arr(){
        int a  = 1* 5;
        return a;  // 行 int 可以到 double
        //4.如果为 void 不加return 返回值  或者直接写return
        //5.同一个类的方法直接调用就可以
        //6.跨类使用需要先创建对象在调用
             B p1 = new B();
             p1.f3();

            class A{
            public void f1(){
                System.out.println("你好,奶盖");
            }
            public void f2(){
                f1();  // 直接使用
                System.out.println("好久不见");
            }
        }
        class B{
            public void f3(){
                A p2 = new A();  // 跨类使用
                p2.f2();
                System.out.println("酷盖");
            }

}



方法的传参机制   重点

    //   1. 基本数据类型的传参机制
        AA a = new AA();
        int n1 = 22;
        int n2 = 23;
        a.swap(n1,n2); //输出结果 22 23 和 23 22 
        System.out.println("交换后 n1 和 n2 的值"+ " " + "n1 = " + n1 +" "+ "n2 = " + n2); //a = 22 b = 23      
    }
}

class AA{

    public void swap(int a,int b){
        System.out.println("交换前 a 和 b 的值"+ " " + "a = " + a +" "+ "b = " + b);
        int tmp;
        tmp = a;
        a = b;
        b = tmp;
        System.out.println("交换后 a 和 b 的值"+ " " + "a = " + a +" "+ "b = " + b);
    }
}
// 分析:
        //1.栈中 有个main栈 其中 a = 23,b = 22
        //1.当执行  a.swap(a,b); 开辟一个独立空间 swap 栈
        //3.其中a,b值互换 但是swap栈 和main 栈互不影响 其中变量不改变彼此
        //4.所以swap栈中a,b值互换 main栈中a,b值不变

        // 总结:** 基本数据类型传递的值是(值拷贝),形参的改变不影响实参(main)



        // 2.引用数据类型的传参机制

        int arr[] = {1,2,3};
        B b = new B();
        b.test(arr);
        System.out.println("main 中的数组元素");
        for(int i = 0; i <arr.length;i++) {
            System.out.print(arr[i] + " ");
        }
        System.out.println();  // 输出结果:23 2 3
        class B{
        public void test(int Arr []){
            Arr [0] = 23;
            System.out.println("test 中的数组元素");
            for(int i = 0; i <Arr.length;i++) {
                System.out.print(Arr[i] + " ");
            }
            System.out.println();
        }


    }


        //分析:  重点 数组是引用数据类型,传递的是地址 指向堆
        //1.执行到int arr[] = {1,2,3}; arr->堆里的地址,地址中存放arr{1,2,3}元素
        //2.执行到 b.test(arr);开辟一个test栈,其中数组也是指向堆中数组元素的相同地址
        //3.执行到Arr [0] = 23; 改变地址中arr[0]的元素
        //4.最后在中执行System.out.print(arr[i] + " ");也是指向那个地址,所以数组元素改变

        //总结:** 引用传递类型传递的是地址,可以通过形参形象实参

        // 对象传递也是引用类型   通过方法会改变属性


        Person p1 = new Person();
        p1.age = 18;
        System.out.println("年龄是 = " + p1.age);
        A a = new A();
        a.test100(p1);
        System.out.println("年龄是 = " + p1.age);
    }
}
class Person{
    int age;
}
class A{
    public void test100(Person p1) {  //形参写类名 + 对象名
      //  p1.age = 20;
      //   p1 = null;  // 结果是18; // 不在指向堆中的地址
        p1 = new Person(); // 在堆中在创建一个对象 不在指向原来的对象  该对象会被回收
        p1.age =20;  // 输出18;

    }
}


 克隆对象://copyPerson 一个对象 但两个对象是独立空间

        Person p1 = new Person();
        p1.name = "奶盖";
        p1.age = 18;

        MyTool tool = new MyTool();
        Person p2 = tool.copyPerson(p1);
        System.out.println("p1名字信息分别为" + " " + p1.name + " " + p1.age);
        System.out.println("p2名字信息分别为" + " " + p2.name + " " + p2.age);
        //判断是不是同一个地址
        System.out.println(p1 == p2);//false代表不是同一个地址
        //p1 p2 是person的对象但这两个是独立的对象,属性相同

    }
}
class Person{
    String name;
    int age;
}
class MyTool{
    // ** 编写方法的思路
    //1.方法的返回类型
    //2.方法的名字
    //3.方法的形参
    //4.方法体 创建一个对象 复制并返回
    public Person copyPerson(Person p1){
        //创建一个新对象
        Person p2 = new Person();
        p2.name = p1.name;;
        p2.age = p1.age;
        return p2;
    }
}



三.重载


        //基本介绍:同一个类中,相同的方法名, 形参列表不同
        //减轻了起名和记名的麻烦,
 //重载细节:
        //1.方法名必须相同
        //2.形参类型:必须不同,或者顺序不同  至少有一个不同
        //3.返回类型无要求  如果两个方法只是返回类型不同 则不能构成重载


		
        class MyCalculator{

            public int calculator(int n1,int n2){
                return n1+n2;
            }
            public double calculator(int n1,double n2){
                return n1+n2;
            }
            public int calculator(int n1,int n2,int n3){
                return n1+n2+n3;
            }

        }
       class Methods1{
            public void max(int n1,int n2){
                if (n1 > n2){
                    System.out.println(n1);
                }else{
                    System.out.println(n2);
                }
            }
            public void max(double n1,double n2){
                if (n1 > n2){
                    System.out.println(n1);
                }else{
                    System.out.println(n2);	
                }
            }
            public double max(double n1,double n2,double n3){

                double max1 = n1 > n2 ? n1:n2;
                return max1 > n3 ? max1 : n3;

            }

四.作用域

  作用域:
        //1.主要的变量是属性(成员变量)和局部变量
        //2.局部变量一般为成员方法中定义的变量(cat类)
        //3.全局变量:作用域为整个类体 Cat类(cry,eat)
        //4.全局变量可以不赋值使用,但是局部变量必须赋值后使用
        Cat c = new Cat();
        c.cry();
        c.eat();
        class Cat{
            int age =  18;
              //  int age ; 全局变量 可以不赋值 结果为默认值
            public void cry(){
                String name = "奶盖";
                System.out.println("在cry中 age = " + age);
                int num; // 局部变量不可以不赋值否则会报错
              //  System.out.println(num);
            }
            public void eat(){
                String name = "酷盖";
                System.out.println("在eat中 age = " + age);
            }

        }


作用域的使用细节:
   	    //1.属性可以和局部变量重名,访问时遵守就近原则
        //2.同一个作用域中,比如同一个方法中,两个局部变量不能重名
        //3.属性的生命周期较长,伴随对象的创建而创建,销毁而销毁。局部变量,生命周期较短,伴随代码块的执行而创建,结束而销毁
        //4.作用域范围不同  全局变量:可以被本类方法使用 也可以被其他类方法使用   局部变量: 只能被本类方法使用
        //5.属性可以加修饰符 但是局部变量不能加修饰符

五.构造器


        //基本介绍:是类的一种特殊方法,主要作用是完成对新对象的初始化
        // 基本语法:
        //修饰符 方法名(形参列表){
        // 方法体 }

        //1.构造器修饰符可以默认
        //2.构造器没有返回值
        //3.方法名和类名要相同
        //4.创建对象时,系统会自动的调用该类的构造器对其进行初始化

        Person p1 = new Person("酷盖",18);
        Person p2 = new Person("奶盖",18);
        System.out.println("p1的信息如下" + " name " + p1.name + " " + " age "  + p1.age);
        System.out.println("p2的信息如下" + " name " + p2.name + " " + " age "  + p2.age);

    }
}
class Person{
    String name;
    int age;
    public Person(String pName , int page){
        name = pName;
        age = page;
    }

}

构造器使用细节:
        //1.一个类可以定义多个构造器,即构造器的重载
        //2.构造器没有返回值
        //3.方法名和类名要相同
        //4.构造器是完成对象的初始化,并不是创建对象
        //5.在创建对象时,系统自动调用该类的构造方法
        //6.当定义构造器的时候默认构造器被覆盖不能使用,需要定义一下默认构造器  例如 Person(){}

// 对象创建的流程分析

        Person p = new Person(18,"奶盖");
        System.out.println(p.age + p.name);

class Person{
    int age = 18;
    String name;
   public  Person(int a ,String n){
        age = a;
        name = n;
    }
    分析:1.加载person类信息,只会加载一次
         2.在堆中完成分配空间(地址)
         3.完成对象的初始化(默认初始化->显式初始化->构造器的初始化)
         4.对象在堆中的地址返回给p