Java 入门 (六)

一、面向对象

1.1 面向过程

回想我们之前写过的代码,我们要做一件事情的时候,会先分析这件事情怎么去做,然后通过代码一步一步去实现。而这一步步的实现是需要我们全程参与,这些过程通过互相之间的调用和协调来完成我们的需求,这种处理问题的方式被我们称为面向过程

代表性的语言:C语言

1.2 面向对象

但是随着需求的增加,代码的内容肯定会也相应的增加,这就代码的复杂性。

回想之前我们学过的数组,遍历一个数组的时候,我们可以写一个for循环来解决。但是要遍历10个数组的时候,怎么办呢?我们使用了方法来进行改进。对一个数组我们有了多种操作:数组的遍历、数组的求最值、数组的反转等,这些我们都用方法进行改进。我们知道所有的方法都是定义在类中,所以我们可以将这些对数组的操作都放在一个类中,以后想要对数组进行操作的时候,只要通过类的具体的实例来调用这些方法完成相应的功能即可。这种处理问题的方式被我们称为面向对象。

代表性的语言:Java

例子

做饭:
    面向过程:买菜-择菜-洗菜-切菜-炒菜-装盘
    面向对象:服务员(点菜)-厨师(炒菜)-服务员(上菜)
买电脑:
    面向过程:分析需求-根据需求找相应配置的电脑-去电脑城-购买到手
    面向对象:将需求提供给懂电脑的对象-这个对象去买电脑-购买到手

1.3 面向过程和面向对象的关系

面向对象是基于面向过程的

1.4 面向对象的好处

将复杂的问题简单化
更符合人类的思维习惯
将我们从问题的执行者,变成了指挥者

1.5 面向对象的特征

封装
继承
多态

二、类与对象

现实世界中是如何描述一个事物的

属性:姓名、年龄         一般都是名词
行为:唱歌、跳舞、闪电鞭  一般都是动词

Java就是为了解决现实世界中的问题而存在的,Java中是如何描述一个事物的呢?

Java中最基本的单位是类,所以我们可以使用类来对现实世界中的事物进行描述

成员变量: 相当于现实中的属性
成员方法: 相当于现实中的行为

成员变量:与之前讲过的局部变量差不多,只不过成员变量是声明在类中方法外的,并且成员变量不用进行初始化就能使用
成员方法:与之前我们使用的方法差不多,只不过这个地方就先不用static了,而是直接被public修饰

2.1 什么是对象?

对象是类的一个具体的表现

比如:
    类:
        汽车
    对象:
        五菱宏光、迈巴赫、宝马

    类:
        学生
    对象:
        郭泰
注意事项:一个java文件中可以放多个类,但是只能有一个被public修饰

2.2 案例:学生类

class Student {

    //成员变量(相当于属性):姓名、年龄
    //姓名
    String name;
    //年龄
    int age;

    //成员方法(相当于行为):吃饭、睡觉、学习
    //吃饭
    public void eat() {

        System.out.println("吃饭");
    }
    //睡觉
    public void sleep() {

        System.out.println("睡觉");
    }
    //学习
    public void study(String ss) {

        System.out.println(ss + "学习");
    }

}

三、使用类中的成员

3.1 创建对象

格式:
    数据类型 对象名 = new 数据类型(...);

格式的解释:
    数据类型:只能是引用数据类型,比如说之前见过的Scanner,也可以是现在创建的Student类
    对象名: 实际上是一个引用,用来存储对象的地址
    =:将在堆上new出来的对象的地址赋值给对象名(引用)
    new:关键字new,用来在堆上开辟空间
    数据类型:同上
    (...):是一个方法(实际上是一个构造方法),有参就传参,无参就不传

3.2 使用成员变量

对象名.成员变量名;

3.3 使用成员方法

对象名.成员方法名(...);

注意: ...的意思是 如果有参就传参,如果无参就留空
public class Demo2 {

    public static void main(String[] args) {

        //1. 数据类型 对象名 = new 数据类型(...);
        Student s = new Student();

        //2. 使用成员变量 对象名.成员变量名;
        s.name = "马保国";
        s.age = 69;

        System.out.println(s.name);
        System.out.println(s.age);

        //3. 使用成员方法 对象名.成员方法名(...);
        s.eat();
        s.sleep();
        s.study("马保国的弟子");

    }
}

四、对象的内存图

4.1 两个对象的内存图

/*
 * 学生类
 */
public class Student {

    //成员变量:姓名、年龄
    String name;
    int age;

    //成员方法:吃饭、睡觉
    public void eat() {
        System.out.println("吃饭");
    }
    public void sleep() {
        System.out.println("Zzzzz");
    }

}

/*
 * 测试类
 */
public class Demo {

    public static void main(String[] args) {

        //1. 创建对象
        Student s = new Student();

        //2. 使用对象调用成员变量
        System.out.println(s.name + "---" + s.age);

        //3. 给成员变量赋值
        s.name = "马云";
        s.age = 56;
        s.eat();
        System.out.println(s.name + "---" + s.age);
        System.out.println("--------------------");

        //2. 创建第二个对象
        Student s2 = new Student();
        System.out.println(s2.name + "---" + s2.age);
        s2.eat();
        s2.name = "马老师";
        s2.age = 55;
        System.out.println(s2.name + "---" + s2.age);

    }
}

image-20201123135523592.png

4.2两个引用指向同一个对象

/*
 * 学生类
 */
public class Student {

    //成员变量:姓名、年龄
    String name;
    int age;

    //成员方法:吃饭、睡觉
    public void eat() {
        System.out.println("没有鸡腿");
    }
    public void sleep() {
        System.out.println("没有睡好");
    }

}

public class Demo2 {

    public static void main(String[] args) {

        Student s = new Student();

        System.out.println(s.name + "---" + s.age);

        s.name = "马云";
        s.age = 56;

        s.sleep();
        System.out.println(s.name + "---" + s.age);
        System.out.println("------------");

        //两个引用指向同一个对象
        Student s2 = s;

        System.out.println(s2.name + "---" + s2.age);

        s2.name = "马老师";
        s2.age = 55;

        s2.sleep();
        System.out.println(s2.name + "---" + s2.age);

    }
}

4.3 对象的创建过程

1. 将要执行的类的字节码加载到方法区中
2. 在栈中声明一个类的引用,这个引用是用来存储真正对象的地址的
3. 在堆上用new开辟了一块空间,产生了一个指向该空间的地址
4. 堆中对象的地址被赋值给了栈中的引用

4.4 成员变量和局部变量的区别

局部变量:声明在方法上或者方法内部
成员变量:声明在类中方法外

声明位置的不同:
    局部变量:声明在方法上或者方法内部
    成员变量:声明在类中方法外
内存中的位置不同:
    局部变量:栈上
    成员变量:堆上
生命周期的不同:
    局部变量:随着方法的调用而存在,随着方法的调用结束而消失
    成员变量:随着对象的创建而存在,随着对象的回收而消失
初始化值的不同:
    局部变量:必须要进行初始化
    成员变量:不用进行初始化,因为它有默认的初始化值
        整数类型: 0
        小数类型: 0.0
        布尔类型: false
        字符类型: '\u0000'
        引用数据类型: null

五、匿名对象

没有名字的对象。 比如:new Student()

5.1 使用场景

1. 对象只使用一次的时候
2. 把匿名对象当做参数来使用
public class Demo3 {

    public static void main(String[] args) {

//      Student s = new Student();
//      
//      //1. 下面要调用sleep、eat方法及name变量,有3次,这个时候使用引用s代替更好
//      s.sleep();
//      s.eat();
//      
//      s.name = "李斯特";


        //2. 如果只调用sleep()方法,用这么一次的话,那么可以使用匿名对象。
//      new Student().sleep();

    }
}
public class Demo4 {

    public static void main(String[] args) {

        //方式一:先创建好一个对象,然后将对象传递给test方法
//      Student s = new Student();
//      test(s);

        //方式二:使用匿名对象
        test(new Student());
    }

    public static void test(Student s) { //要的是一个类类型,实际上需要的是该类的对象

        System.out.println(s.name + "---" + s.age);
    }
}

5.2 注意事项

如果使用匿名对象给类中的成员赋值,那么再去使用匿名对象去访问该成员的时候,并不能取到赋的值(因为这是两个不同的对象)
public class Demo5 {

    public static void main(String[] args) {

        /*
         *  每new一下,都会创建一个新的对象
         *  
         *  下面使用匿名对象的过程中,new了4次,也就说创建了4个对象 
         *
         *  每个对象的成员变量的值不是共享的,是自己独有的  
         */
        new Student().name = "张三";
        new Student().age = 56;

        System.out.println(new Student().name + "---" + new Student().age);
    }
}

六、封装

隐藏了事物的属性及具体的实现细节,而对外提供公共的访问方式

6.2 好处

1. 提高了代码的安全性
2. 提高了代码的复用性

6.3 原则

1. 隐藏事物的属性
2. 隐藏事物的实现细节
3. 对外提供公共的访问方式
/*
 *  我们发现下面的代码出现了逻辑上的错误,因为年龄可以设置为非法数据 -50,
 *  
 *  如何处理呢?
 *      1. 要想对年龄age 进行范围设置,肯定要需要 分支结构来进行判断
 *      2. 分支结构都是放在方法中的,那么就定义一个方法来进行年龄的判断
 *  
 *  方法放在那里呢?
 *      1. 方法肯定是要写在类中的,但是应该哪个类里面
 *      2. 测试类中肯定是不行,因为测试类中主要是用来进行代码测试,这种逻辑性的判断尽量不要放在测试类中
 *      3. 所以只能放在学生类中
 *  
 *  解决方法:
 *      1. 在学生类Student中新建一个方法用来判断年龄是否合理
 *  
 *  又发现了一个问题,写好的方法,别人不使用。所以我们要强制使用户使用我们这个方法,而不能直接访问到成员变量
 *  
 *  Java中隐藏一个成员变量,以使这个成员变量只能本类中被访问,出了本类就不能再被访问到了,这个关键字是private
 */


/*
 * 学生类
 */
class Student {

    //成员变量:姓名、年龄
    String name;
    private int age;

    //成员方法:吃饭、睡觉
    public void eat() {
        System.out.println("吃饭");
    }
    public void sleep() {
        System.out.println("睡觉");
    }

    //判断年龄是否合理,如果合理就设置
    public void setAge(int a) {

        if(a >= 0 && a <= 130) {
            age = a;
        }else {
            System.out.println("您输入的年龄有误!");
        }
    }

    //定义一个方法,用来展示年龄和姓名
    public void show() {
        System.out.println(name + "---" + age);
    }
}


/*
 * 测试类
 */
public class Demo {

    public static void main(String[] args) {

        //1. 创建对象
        Student s = new Student();

        //2. 使用对象调用成员变量
        s.name = "张三";
//      s.age = -50;

        s.setAge(-50);

        s.show();
//      System.out.println(s.name + "===" + s.age);
    }
}

七、private关键字

private可以修饰成员变量、成员方法,被修饰的成员只能在本类中被访问

被private修饰的成员只能在本类中被访问,外界访问不了,但是我们可以通过在本类中可以设置一个可以被外界访问的方法(这个本类的方法中,访问本类的私有成员),来间接的访问本类私有的成员
class Car {

    private String name;         //被私有了,只能在本类中被访问
    int age;

    private void drinkOil() {    //被私有了,只能在本类中被访问
        System.out.println("喝油");
    }

    public void show() {

        drinkOil();   //访问本类的喝油方法
        System.out.println(name + "---" + age);
    }
}

public class PrivateDemo {

    public static void main(String[] args) {

        Car c = new Car();

        c.show();   //通过访问show方法,间接的访问Car类中私有的成员变量name及私有的成员方法drinkOil方法
    }
}

八、getter和setter方法

因为成员变量已经被private修饰了,只能在本类中被访问了,外界访问不了。为了让外界访问到,我们可以设置一个对外提供公共的方法来进行设置和获取,这些方法一般被我们声明为getXxx和setXxx方法。

其中:setXxx用来设置成员变量的值 getXxx用来获取成员变量的值。 Xxx是成员变量名,注意第一个X大写

class Student {

    //成员变量
    private String name;
    private int age;

    //getXxx和setXxx方法
    public void setName(String n) {

        name = n;
    }
    public String getName() {

        return name;
    }

    public void setAge(int a) {

        age = a;
    }
    public int getAge() {

        return age;
    }


    //成员方法
    public void eat() {

        System.out.println("吃饭");
    }
    public void sleep() {

        System.out.println("睡觉");
    }

    //展示成员变量的方法
    public void show() {

        System.out.println(name + "---" + age);
    }

}

public class Demo {

    public static void main(String[] args) {

        //1. 创建对象
        Student s = new Student();

        //2. 通过setXxx方法给成员变量赋值
        s.setName("张三");
        s.setAge(60);

        //3. 方式一:通过getXxx方法获取成员变量的值
        System.out.println(s.getName() + "---" + s.getAge());

        //4. 方式二:通过自定义的show方法来获取成员变量的值
        s.show();
    }
}

九、this关键字

哪个对象访问了方法,那么方法中的this就代表哪个对象

class Student {

    //成员变量
    private String name;
    private int age;

    //getXxx和setXxx方法
    public void setName(String name) {

        /*
         * 下方的两个name都是局部变量的name,是同一个,这个name变量会在方法调用结束之后被销毁
         * 
         * 变量的访问顺序:
         *      1. 会先访问局部变量
         *      2. 如果局部变量没有,会去成员位置去找
         *      3. 如果成员位置没有,那就报错
         * 
         * 我们知道 对象名.变量 就可以访问成员位置的变量了
         */
        this.name = name;
    }
    public String getName() {

        return name;
    }

    public void setAge(int age) {

        this.age = age;
    }
    public int getAge() {

        return age;
    }


    //成员方法
    public void eat() {

        System.out.println("吃饭");
    }
    public void sleep() {

        System.out.println("睡觉");
    }

    //展示成员变量的方法
    public void show() {

        System.out.println(name + "---" + age);
    }

}

public class Demo {

    public static void main(String[] args) {

        Student s = new Student();

        s.setName("张三");
        s.setAge(50);

        System.out.println(s.getName() + "---" + s.getAge());


        Student s2 = new Student();
        s2.setName("李四");
        s2.setAge(66);
        System.out.println(s2.getName() + "---" + s2.getAge());
    }
}

评论 0

还没有评论,来说点什么吧。

提交后需要审核才会公开。