黑马程序员-Java基础:面向对象-2

——Java培训、Android培训、iOS培训、.Net培训、期待与您交流! ——-

day07:面向对象(上)


一、成员变量和局部变量的区别

1. 在类中的位置不同:
成员变量:类中方法外
局部变量:方法定义或方法声明上

2. 在内存中的位置不同:
成员变量:在堆内存中
局部变量:在栈内存中

3. 生命周期不同:
成员变量:随着对象的创建而存在,随对象的消失而消失
局部变量:随方法体的调用而存在,随方法调用完毕而消失

4. 初始化值不同:
成员变量:有默认初始化值
局部变量:没有默认值,在使用之前必须显示初始化,赋值后才能使用

二、Java中参数的传递问题
Java中方法的参数可以有两种类型:
基本数据类型:byte, short, int, long ,float, double, char, boolean
引用数据类型:某个类的变量,基本类型数组
1.当方法被调用时,如果传入方法的实际参数是基本数据类型,那么如果在方法体中对参数进行修改,将不会影响实际参数的值,因此基本数据类型的参数传递方式是值传递。
2.当方法被调用时,传入方法的实际参数是某一个类的变量,或基本类型数组的变量时,此时实际传入方法的是该类对象或数组在内存中的地址值,当在方法体内对该地址进行操作时,实际上操作的是地址所指向的对象,因此会使对象发生改变,但这种传递方式仍然属于值传递,因为传递的是地址的值。
注:Java中参数传递的方式为值传递
Java参数传递示例代码:
参数为基本类型变量
下面的代码通过一个方法实现两个整数互换值的操作

public class ParapassDemo {
    public static void main(String[] args) {
        int a = 10;
        int b = 29;
        System.out.println("交换前: a = " + a + ",b = " + b);
        swap(a, b);
        System.out.println("交换后: a = " + a + ",b = " + b);
    }

    public static void swap(int a, int b) {
        int temp = a;
        a = b;
        b = temp;
    }
}

输出结果:
交换前: a = 10,b = 29
交换后: a = 10,b = 29

很可惜从结果上看,该程序并没有完成预期的目的,交换前后,实际参数a,b的值没有交换,下面用一张图来解释为什么出现这种结果。
这里写图片描述
从上图可以看出,方法中交换的仅仅是局部变量a,b的值,而实际参数在main()方法中一直没有改变,因为调用方法时仅仅将实参的值传递给了swap()方法。

参数为引用类型

public class ParamPassDemo {
    public static void main(String[] args) {
        Person p1 = new Person();
        Person p2 = new Person();
        System.out.println("交换前: p1 = " + p1 + ",p2 = " + p2);
        swap(p1, p2);
        System.out.println("交换后: p1 = " + p1 + ",p2 = " + p2);

    }

    public static void swap(Person p1, Person p2) {
        Person temp = p1;
        p1 = p2;
        p2 = temp;
    }
}

/*
 * 定义一个Person类 
 */
class Person {
}

输出结果:
交换前: p1 = blogcode.Person@1e58cb8,p2 = blogcode.Person@179935d
交换后: p1 = blogcode.Person@1e58cb8,p2 = blogcode.Person@179935d

从输出结果看到,和基本类型类似,p1和p2所指向的对象没有变化,变化的只是局部变量中临时的p1和p2的引用
请看下面这张图解:
这里写图片描述

三、匿名对象
所谓的匿名对象,从字面上理解就是没有命名的对象,实际意义其实也是如此,匿名对象就是没有指定变量名称,只能使用一次的对象。
例如:
new Person();
new Cat();
new String();
……

应用场景

1. 调用某个对象的方法,且该对象仅仅使用这一次
2. 作为实际参数,直接传递给某个方法的形参。

四、封装
1.概念:隐藏类的属性和实现细节,对外提供公共的访问方式。
要较好的理解封装的概念,需要先了解Java提供的访问权限修饰符。
以下三个关键字在Java中用于为类和类中的成员设定访问权限:

  • public : 被该关键字修饰的元素(类,成员…)可以被任何其他元素访问、
  • private:被该关键字修饰的元素表示除了类的内部成员之外不能被任何元素访问
  • protected:只有继承该类才能访问类中被protected 修饰的成员
  • 默认权限:包访问权限,在同一个包中可以访问的元素。

2.Java提供访问控制权限主要有两个原因:
1.让类的使用者无法触及他们不该触及的部分,这些部分是类在内部操作数据所必须的,但不应该暴露给用户使用,也就是隐藏实现细节
2.当类的设计者改变类的内部实现方式时,不用担心会影响到使用该类的用户,例如当你以一种简单的方式实现了某一个类,但之后你发现这种简单的实现方式效率并不高,这时你可以放心的改变这个类的内部实现,而不需要担心会影响用户正常使用该类。

由此也得出了封装的优点
A.隐藏实现细节,提供公共访问方式
B.提高代码复用性
C.提高代码的安全性

3.封装的典型应用示例
需求:定义一个Person类,将成员变量私有,并提供公共的访问方式。
代码:

public class Person {
    //私有的成员变量
    private String name;
    private 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;
    }

}

4.this关键字
this关键字代表当前类的对象的引用
通俗的理解:哪个对象调用该方法,那么该方法内部的this关键字就代表那个对象
应用场景:解决局部变量和成员变量同名问题

五、构造方法
1.作用:用于给对象中的成员变量进行初始化操作
2.定义格式

  • 方法名与类名相同
  • 没有返回值
  • 没有返回值类型、
    例如:public Person(){}

3.注意事项

  • 如果没有显示的给出构造方法,系统将提供一个默认的空参构造方法
  • 如果我们给出了构造方法,系统将不再提供默认构造方法如果这个时候,我们要使用无参构造方法,就必须自己给出。
    推荐:永远手动自己给出无参构造方法

4.一个标准的自定义类案例

/*
 * 一个标准的学生类
 */
public class Student {
    /*
     * 私有的成员变量:
     * 姓名: String name
     * 年龄: int age
     */
    private String name;
    private int age;

    /*
     * 一个空参构造方法
     */
    Student() {
    }

    /*
     * 一个带参数构造方法,用于初始化成员变量
     */
    Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    /*
     * 与成员变量相对应的setXxx()/getXxx()方法
     * 用于获取和修改成员变量
     */
    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 class StudentDemo {
    /*
     * 主方法:用于创建学生类对象,调用学生类对象的方法
     */
    public static void main(String[] args) {
        //创建学生类对象
        //空参构造创建对象
        Student student1 = new Student();
        //通过带参构造创建对象,并初始化成员变量
        Student student2 = new Student("小明", 18);

        //调用setXxx()方法设置成员变量
        student1.setName("小红");
        student1.setAge(17);
        //调用getXxx()方法获取成员变量
        String name1 = student1.getName();
        int age1 = student1.getAge();
        String name2 = student2.getName();
        int age2 = student2.getAge();

        //输出获取的成员变量
        System.out.println("student1:" + name1 + "," + age1);
        System.out.println("student2:" + name2 + "," + age2);

    }
}

测试结果:
student1:小红,17
student2:小明,18

六、理解创建对象的过程
代码:Student s = new Student();做了哪些事情?

1. 把Student.class文件加载到内存中
2. 在栈内存为变量s开辟空间
3. 在堆内存为学生对象开辟空间
4. 对学生对象的成员变量进行默认初始化 (name = null, age = 0)
5. 对学生对象的成员变量进行显示初始化
6. 通过构造方法给成员变量进行初始化
7. 对象构造并初始化完毕,把对象的地址赋值给变量s
以上的初始化步骤由JVM完成,理解对象的创建过程有助于对Java程序执行流程的掌握,并且在遇到错误的时候能够快速找到问题所在。

七、static关键字
static 代表静态的意思,用于修饰成员变量和成员方法。
1.静态的特点:

  • A:随着类的加载而加载 。 、
  • B:优先于对象存在
  • C:被类的所有对象共享
    举例:班级的学生应该共用同一个班级编号。其实这个特点也是在告诉我们什么时候使用静态?
    如果某个成员变量是被所有对象共享的,那么它就应该定义为静态的。
  • D:可以通过类名调用
    也可以通过对象名调用。 推荐使用类名调用。

一个示例代码说明静态的特点:

class Student {
    //非静态变量
    int num = 10;

    //静态变量
    static int num2 = 20;

    //静态方法
    public static void method(){
        System.out.println("这是一个静态方法");
    }
}

class StudentDemo {
    public static void main(String[] args) {
        //创建学生类对象
        Student s = new Student();
        //通过对象名调用非静态成员变量
        System.out.println("对象名调用非静态成员变量num : " + s.num);
        //因为优先于对象存在,所以可以通过类名来调用
        System.out.println("类名调用静态成员变量num2 : " + Student.num2);
        //也可以通过对象名调用静态成员变量,但不提倡这么做
        System.out.println("对象名调用静态成员变量num2 : " + s.num2);
        //通过类名调用静态方法
        Student.method();
    }
}

运行结果:
这里写图片描述

2.静态的注意事项:
-在静态方法中只能访问静态成员
-静态方法中不隐式包含this关键字:静态是随着类的加载而加载,this是随着对象的创建而存在。
示例代码:

class Teacher {
    public int num = 10;
    public static int num2 = 20;

    public void show() {
        System.out.println(num); //隐含的告诉你访问的是成员变量
        System.out.println(this.num); //明确的告诉你访问的是成员变量
        System.out.println(num2);

        //function();
        //function2();
    }

    public static void method() {
        //无法从静态上下文中引用非静态 变量 num
        //System.out.println(num);
        System.out.println(num2);

        //无法从静态上下文中引用非静态 方法 function()
        //function();
        function2();
    }

    public void function() {

    }

    public static void function2() {

    }
}

class TeacherDemo {
    public static void main(String[] args) {
        //创建对象
        Teacher t = new Teacher();
        t.show();
        System.out.println("------------");
        t.method();
    }
}

运行结果:
这里写图片描述

3.静态变量和成员变量的区别
-A:所属不同
静态变量:属于类,类变量
成员变量:属于对象,对象变量,实例变量
-B:内存位置不同
静态变量:方法区的静态区
成员变量:堆内存
-C:生命周期不同
静态变量:静态变量是随着类的加载而加载,随着类的消失而消失
成员变量:成员变量是随着对象的创建而存在,随着对象的消失而消失
-D:调用不同
静态变量:可以通过对象名调用,也可以通过类名调用
成员变量:只能通过对象名调用

八、Java中类的组成
类的组成:

  • 成员变量
  • 构造方法
  • 成员方法
    • 根据返回值:
      • void类型
      • 非void类型
    • 根据形式参数:
      • 空参方法
      • 有参方法
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值