面向对象的基本概念

面向对象和面向过程的区别在于:面向过程每一个功能的具体实现都需要自己实现,就像是公司的职员,需要自己去动手完成每一个工作;而面向对象则更像公司的管理人员,只需要通过调度负责不同功能的职员去完成需要的任务,不需要关注每个职员的具体工作。

什么是面向对象

1、面向对象是一种编程思想。

2、面向对象是一种思考问题的思维方式。

建立面向对象思维方式

1、先整体,再局部。

2、先抽象,再具体。

3、能做什么,再怎么做。

如何学习面向对象

1、掌握一门面向对象语言的语法。

2、熟悉面向对象的设计原则。

3、熟悉面向对象的设计模式。

类与对象

类是分类、类别的意思;类是一组具有相同特性(属性)与行为(方法)的事物集合。通过分类,我们可以区别不同的事物种类。

对象是一个个性的产物,是一个个体的特征。

类有属性和方法组成,属性就相当于一个个的特征,方法就相对于人的一个个行为,例如:说话、吃饭、唱歌、睡觉等。

类是一个抽象的概念,而对象则是一个具体的事物。可以将很多拥有相同特征或者方法的对象归纳为某一类,而类可以包含很多不同的对象。

类的定义

// 自定一个类(类型)
class Horse {
    // 在类中定义属性(特征)
    String name;
    int age;
    
    public void run() {
        System.out.println("我是" + name + ", 我今年" + age + "岁了, 我日行千里!");
    }

    public void eat() {
        System.out.println("我是赤兔马, 我特别能吃!");
    }

}

对象的定义和调用

public class Demo01 {
    public static void main(String[] args) {
        // 创建一个Horse类型的对象
        Horse h = null;
        h = new Horse();
        // 调用对象的属性
        h.name = "赤兔马";
        h.age = 350;
        // 调用对象的方法
        h.run();
        h.eat();
    }
}
类的封装性

封装的概念

  1. 封装性是面向对象思想的三大特征之一。

  2. 封装就是隐藏实现细节,仅对外提供访问接口。

封装有:属性的封装、方法的封装、类的封装、组件的封装、模块化封装、系统级封装...

封装的好处与缺点

封装的好处:

  1. 模块化
  2. 信息隐藏
  3. 代码重用
  4. 插件化易于调试
  5. 具有安全性

封装缺点:会影响执行效率。

为什么要进行封装?

如果类的属性没有进行封装,那么在本类之外创建对象后,可以直接访问属性,属性的值可以被随意的修改;可以通过private关键字设置类的属性有私有属性。如果我们在类外部想要访问私有属性,我们需要提供公有的方法来间接访问。

封装性是面向对象的三大特征之一,封装的本质是隐藏细节,仅对外提供统一的访问接口,一个个封装的东西又组成了另一个东西。

public class Demo02 {
    public static void main(String[] args) {
        Person person = new Person();
        person.setName("菲菲");
        person.getName();
    }
}


class Person {
    // 属性的封装
    private String name;

    // 对外提供一个为name 属性设置值的方法
    public void setName(String name) {
        this.name = name;
    }

    public void getName() {
        System.out.print(this.name);
    }
}

成员变量和局部变量
  1. 在类中的位置不同,成员变量是在类中定义的,局部变量在方法中或者方法的参数。
  2. 在内存中的位置不同,成员变量:在堆内存(成员变量属于对象,对象进堆内存);局部变量:在栈内存(局部变量属于方法,方法进栈内存)。
  3. 声明周期不同,成员变量随着对象的创建而存在,随着对象的销毁而消失;局部变量随着方法的调用而存在,随着方法的调用完毕而消失。
  4. 初始化值不同,成员变量有默认初始化值,引用类型默认为null,局部变量没有默认初始化值,必须定义,赋值,然后才能使用。

局部变量名称可以和成员变量名称一样,在方法中使用的时候,采用的是就近原则。如果想访问的是成员变量而不是局部变量可以使用this.valueName的方式来进行访问。

构造方法
  1. 构造方法就是类构造对象时调用的方法,用于对象的初始化工作;
  2. 构造方法是实例化一个类的对象时,也就是 new 的时候,最先调用的方法。

构造方法的定义:

构造方法是在类中定义的,构造方法的定义格式:方法名称与类名称相同,无返回值类型的声明。

对象的实例化语法:

Dog dog = new Dog(); // new Dog 后面有个括号,带括号表示调用了方法,此时调用的方法就是构造方法;

public class Demo03 {
    public static void main(String[] args) {
        // Dog dog = new Dog();
         Dog dog = new Dog(17, "小黄");
    }
}

class Dog {
    private int age;
    private String name;
    // 构造方法
    public Dog() {
        System.out.print("构造方法执行了");
    }
    // 构造方法的重载
    public Dog(int age, String name) {
        this.age = age;
        this.name = name;
        System.out.println("构造方法重载执行了");
    }
}

在类中没有对构造方法进行重载时,构造方法是默认存在的,如果在类中进行了构造方法的重载,默认的构造方法就会失效。

构造方法调用构造方法:

class Dog {
    private int age;
    private String name;

    // 构造方法的重载
    public Dog(int age, String name) {
        this(name);
        this.age = age;
        System.out.println("有两个参数的构造方法");
    }
    
    public Dog(String name) {
        this.name = name;
        System.out.println("只有一个参数的构造方法");
    }
}

在构造方法中调用另一个构造方法,使用this(...),该句代码必须在第一句。

static 关键字

可以使用static对类中的属性或者方法进行修饰,被修饰过的属性叫做静态变量;被修饰过的方法叫做静态方法。它们仅能调用其他的static方法、只能访问static数据,不能以任何形式引用this或super。

/*
1. 静态变量或方法不属于对象,依赖类。
2. 静态变量是全局变量,生命周期从类被加载后一直到程序结束。
3. 静态变量只有存一份,在静态方法区存储。
4. 静态变量是本类所有对象共享一份。
5. 建议不要使用对象名去调用静态数据,直接使用类名调用。
6. static修饰一个方法,那么该方法属于类,不属于对象,直接用类名调用。
7. 静态方法不能访问非静态属性和方法,只能访问静态。
*/
public class Demo05 {
    public static void main(String[] args) {
        Role 刘备 = new Role("刘备", "蜀国");
        刘备.getInfo();

        String country = Role.getCountry();  // 调用静态方法
        System.out.print(country);
    }
}

class Role {
    private String name;
    private static String country = "蜀国"; // 定义静态属性

    public Role(String name, String country) {
        this.name = name;
        this.country = country;
    }

    public void getInfo() {
        System.out.println("name=" + this.name + ",country=" + Role.country);  // 通过类名获取属性
    }

    public static String getCountry() {  // 定义一个静态方法
        return Role.country;
    }
}

所有对象共同的属性或方法,我们可以定义为静态的。

main 方法分析
public static void main(String[] args){
	// 代码块
}

public:公有的,最大的访问权限。

static:静态的,无需创建对象,

void:表示没有返回值,无需向JVM返回结果。

main:方法名,固定的方法名

String[] args:表示参数为字符串数组,可以在调用方法时传入参数。

代码块

普通代码块:在普通方法中写的代码块;

public static void mian(String[] args){
    // 限制作用域,类似js中的块级作用域
    {
        int i = 1;  // 只能在这个花括号中访问
    }
}

构造代码块:在类中定义的代码块;

class Student{
	{
		// 构造块中的代码在创建新对象时都会被执行
		// 构造块中的代码比构造方法先执行
		System.out.println("我是构造代码块");
	}
}

静态代码块:在类中使用static 定义的代码块;

class Student{
    static{  
        // 静态代码块只会执行一次,只有在第一次使用这个类创建对象时会调用
        // 静态代码块的优先级高于构造代码块
        // 在项目中开发中,通常会使用静态代码块来初始化只调用一次的数据
        System.out.println("我是静态代码块");
    }
}
单例设计模式

作用:保证一个类仅有一个实例,并提供一个访问它的全局访问点。

实现思路:

  1. 构造方法私有化
  2. 声明一个本类对象
  3. 给外部提供一个静态方法获取对象实例

两种实现方式:

1、饿汉式

class Singleton1 {
    private Singleton1() {
    }

    private static Singleton1 s = new Singleton1();

    public static Singleton1 getInstance() {
        return Singleton1.s;
    }

    public void print() {
        System.out.println("测试方法");
    }
}

2、懒汉式

class Singleton2 {
    private Singleton2() {

    }

    private static Singleton2 s;

    public static Singleton2 getInstance() {
        if (Singleton2.s == null) {
            Singleton2.s = new Singleton2();
        }

        return Singleton2.s;
    }

    public void print() {
        System.out.println("测试方法2");
    }
}

在项目中为什么要试用单例呢?单例有什么样的好处呢?

在项目中可能会设计一些工具类,通常工具类,只有功能方法,没有属性,并且工具类可能会被频繁的调用,这样做的目的是为了节省重复创建对象所带来的内存消耗,从而来提高效率。