文章目录

  • 面向对象
  • 类和对象基本使用
  • 对象的内存图
  • 构造器
  • this关键字
  • 对象三大特征: 封装
  • 成员变量和局部变量区别


面向对象

面向对象介绍

  • 并不是一个技术,而是一种编程指导思想。
  • 把现实世界的具体事物全部看成一个一个的对象来解决实际问题。

为什么要用面向对象编程?

  • 生活中我们解决问题就是按照对象化的方式进行的。如果程序也能够按照生活的中的方式来解决问题,那么程序就更符合人类的思维习惯,代码看起来会更易理解、更简单、更易维护

面向对象重点学习什么?

  • 学习如何自己设计对象并使用
  • 学习获取已有对象并使用

类和对象基本使用

类(设计图):是对象共同特征的描述, 相当于设计图纸

对象:是真实存在的具体实例。

在Java中,必须先设计类,才能获得对象。

我们看一下如何定义类, 并通过类获取对象的?

  • 定义类的方法如下
public class 类名 {
		// 1、成员变量(代表属性)
		// 2、成员方法(代表行为)
		// 3、构造器 (后面学习)
		// 4、代码块 (后面学习)
		// 5、内部类 (后面学习)
}
public class Car {
		// 属性 (成员变量)
		String name;
		double price;
		
		// 方法 (成员行为)
		public void start(){

		}
		public void run(){

		}
}
  • 当有了类之后, 我们就可以获取对象: 类名 对象名 = new 类名();
Car c1 = new Car();
  • 获取到对象之后, 我们就可以使用对象的属性和方法
  • 访问属性: 对象名.成员变量
  • 访问方法: 对象名.成员方法
// 访问属性
c1.name;
c1.parice;

// 访问方法
c1.start();
c1.run();

定义类的补充注意事项

  • 成员变量的完整定义格式是:修饰符 数据类型 变量名称 = 初始化值; 但是不同对象的变量值肯不同, 所以一般无需指定初始化值,存在默认值
  • 类名首字母建议大写,且有意义,满足“大驼峰模式”。
  • 一个Java文件中可以定义多个class类,且只能一个类是public修饰而且public修饰的类名必须成为代码文件名。
  • 实际开发中建议还是一个文件定义一个class类

对象的内存图

例如我们有如下两个类, 他们在内存中是如何执行的呢?

public class Car {
		// 成员变量(属性)
		String name;
		double price;
		// 方法(行为)
		public void start(){
				System.out.println(name+"启动了!");
		}
		public void run(){
				System.out.println("售价为:" + price +"的" + name+"跑的快!");
		}
}
public class Test {
		public static void main(String[] args) {
				Car c1 = new Car();
				c1.name = "奔驰GLC";
				c1.price = 39.78;
				System.out.println(c1.name);
				System.out.println(c1.price);
				c1.start();
				c1.run();
					
				Car c2 = new Car();
				c2.name = "宝马X3";
				c2.price = 38.98;
				System.out.println(c2.name);
				System.out.println(c2.price);
				c2.start();
				c2.run();
		}
}
  • 我来画图, 分步骤给大家讲解一下在内存中是如何执行的
  • 首先会执行Test类, 将Test类中的main方法提到方法区
  • 执行main方法, 将main方法放入栈内存中执行

java 获取某个对象是否是某个接口的实现 java如何获取对象的类型_开发语言

  • 依次执行main方法中的语句
  • 执行第一行语句Car c1 = new Car();时, 会将Car这个类(以及他的属性和方法)提到方法区
  • 在栈内存中声明一个变量, 由于是new出来的对象, 会放在堆内存, 那么声明的变量c1保存的是堆内存中的地址
  • new Car在对象中开辟出来的空间, 会存放Car这个类的属性和方法, 由于属性未初始化, 是默认值, 方法存放的是引用地址

java 获取某个对象是否是某个接口的实现 java如何获取对象的类型_开发语言_02

  • 继续执行main方法的代码
  • c1.name = "奔驰GLC";将堆内存中的name属性赋值为: 奔驰GLC
  • c1.price = 39.78;将堆内存中的price属性赋值为: 39.78
  • System.out.println(c1.name); System.out.println(c1.price);再打印name和price

java 获取某个对象是否是某个接口的实现 java如何获取对象的类型_开发语言_03

  • 后面执行方法的代码
  • 会根据c1保存的地址找到start方法和run方法
  • 再分别将start方法和run方法分别放入栈内存中执行

  • 下面main方法中的c2同理, 会在堆内存中重新开辟一个新的空间, 将地址赋值给栈内存中的变量c2

java 获取某个对象是否是某个接口的实现 java如何获取对象的类型_java_04

垃圾回收 :

  • 注意:当堆内存中的类对象或数组对象,没有被任何变量引用(指向)时,就会被判定为内存中的“垃圾”。
  • Java存在自动垃圾回收器,会定期进行清理

构造器

学习目的:

  • 真正知道对象具体是通过什么得到的。
  • 能够掌握为对象赋值的其他写法。

构造器的作用 :

  • 用于初始化一个类的对象,并返回对象的地址。

构造器的定义格式 : 修饰符 类名(形参列表){}

构造器的分类 :

  • 无参数构造器(默认存在的):初始化的对象时,成员变量的数据均采用默认值。
  • 有参数构造器:在初始化对象的时候,同时可以为对象进行赋值。
  • 示例如下 :
public class Car {
                                          
		// 无参数构造器
		public Car(){
				...
		}
                    
		// 有参数构造器
		public Car(String n, String b){
				...
		}
}

前面我们所使用的其实就是无参数构造器, 因为无参数构造器是默认存在的

我们来看一下有参数构造器如何使用吧 :

  • 例如: 定义了如下一个类, 类中使用有参数构造器
public class Test {
    String name;
    int age;
    double height;

		// 有参数构造器
    public Test(String a, int b, double c) {
        name = a;
        age = b;
        height = c;
    }
}
  • 那么我们创建对象的时候, 就可以传入数据
  • 不需要像无参数构造器一样, 拿到实例对象后, 还需要依次赋值
public static void main(String[] args) {
                    
    Test test1 = new Test("chenyq", 18, 1.88);
                    
    System.out.println(test1.name); // chenyq
    System.out.println(test1.age); // 18
    System.out.println(test1.height); // 1.88
}

注意事项 :

  • 任何类定义出来,默认就自带了无参数构造器,写不写都有。
  • 一旦定义了有参数构造器,无参数构造器就没有了,此时就需要自己写一个无参数构造器了。

this关键字

this关键字可以出现在成员方法、构造器中,代表当前对象的地址

  • 作用:访问当前对象的成员变量、成员方法。

this出现在有参数构造器中的用法 :

  • 例如: 刚刚我们在类中定义的有参数构造器可以写成下面这种格式
public class Test {
    String name;
    int age;
    double height;

    public Test(String name, int age, double height) {
        this.name = name;
        this.age = age;
        this.height = height;
    }
}

this出现在成员方法中的用法 :

public class Test {
    String name = "chenyq";

    public void introduce() {
        System.out.println("my name is" + " " + this.name);
    }

    public Test(String name) {
        this.name = name;
    }
}

对象三大特征: 封装

面向对象的三大特征:封装,继承,多态。

  • 什么是封装? 隐藏实现细节,暴露出合适的访问方式。(合理隐藏、合理暴露)

为什么要用封装?我们来看下面的例子 :

  • 定义如下一个类:
public class Student {
		int age;
}
  • 设置年龄变量
Student s = new Student();
s.age = -23;

我们发现, 上面的做法是允许的, 但是从业务角度来说, 其实是不规范的(因为年龄没有负值), 外部可以随意修改我们内部的变量是比较危险的

封装的实现步骤 :

  • 一般对成员变量使用private关键字修饰进行隐藏,private修饰后该成员变量就只能在当前类中访问。
  • 提供public修饰的公开的getter、setter方法暴露其取值和赋值。

示例代码 :

  • 对类中的操作
public class Student {
    // private定义的变量, 外部无法访问
    private int age;

    // 1.通过getter函数, 暴露出去
    public int getAge() {
        return this.age;
    }

    // 2.通过setter函数, 暴露出去同时又可以设置
    public void setAge(int age) {
        // 判断age符合规范再设置
        if (age >= 0 && age <= 200) {
            this.age = age;
        } else {
            System.out.println("请输入正确的年龄");
        }
    }
}
  • 设置获取的演示
public static void main(String[] args) {
    Student stu1 = new Student();

    // 通过setter函数设置age
    stu1.setAge(18);
    // 通过getter函数获取age
    System.out.println(stu1.getAge());
}

封装的好处小结 :

  • 加强了程序代码的安全性
  • 适当的封装可以提升开发效率,同时可以让程序更容易理解与维护。

标准的封装需满足以下要求 :

  • 成员变量使用 private
  • 提供每一个成员变量对应的 setXxx() / getXxx()
  • 必须提供一个无参构造器

成员变量和局部变量区别

区别

成员变量

局部变量

类中位置不同

类中,方法外

常见于方法中

初始化值不同

有默认初始化值

没有,使用之前需要完成赋值

内存位置不同

堆内存

栈内存

生命周期不同

随着对象的创建而存在,随着对象的消失而消失

随着方法调用而存在, 随着方法运行结束消失

作用域

在所归属的大括号中