类与对象

类与对象

1. 面向对象与面向过程

什么是面向过程

概述:自顶而下的编程模式
把问题分解成一个一个步骤,每个步骤用函数实现,依次调用即可
就是说,在进行面向过程编程的时候,不需要考虑那么多
上来先定义一个函数,然后使用各种诸如if-else、for-each等方式进行代码执行
最典型的用法就是实现一个简单的算法,比如实现冒泡排序

什么是面向对象

概述:将事务高度抽象化的编程模式
将问题分解成一个一个步骤,对每个步骤进行相应的抽象,形成对象
通过不同对象之间的调用,组合解决问题
也就是说,在进行面向对象进行编程的时候,要把属性、行为等封装成对象,然后基于这些对象及对象的能力进行业务逻辑的实现
比如:想要造一辆车,上来要先把车的各种属性定义出来,然后抽象成一个Car类

面向对象的五大基本原则

五大基本原则:
单一职责原则(Single-Responsibility Principle)
开放封闭原则(Open-Closed principle)
里氏替换替换原则(Liskov-Substituion Principle)
依赖倒置原则(Dependency-Inversion Principle)
接口隔离原则(Interface-Segregation Principle)

区别

  • 面向过程:性能比面向对象高,因为类调用时需要实例化,开销比较大,比较消耗资源
    所以当性能是最重要的考量因素时,比如单片机,嵌入式开发,Linux/Unix等一般采用面向过程开发
    但是面向过程没有面向对象易维护,易复用,易扩展
  • 面向对象:易维护,易复用,易扩展;因为面向对象有封装,继承,多态性的特性
    所以可以设计出低耦合的系统,使系统更加灵活,更加易于维护
    但是面向对象性能比面向过程低

2. 类与对象的概念

1.什么是类

  • 类:指的是对客观事物的一种描述,是对现实中一类具有共同属性和行为的事物的抽象。

2.什么是对象

  • 对象:指的是具体存在的事物,是能够看得到摸的着的真实存在的实体。

3.成员变量

成员变量(Member Variable)也称为实例变量(Instance Variable),是定义在类中的变量。它们属于类的每个对象实例,并且可以被类中的所有成员方法访问和使用。

下面是一个简单的例子,演示了一个名为Person的类和其中的成员变量:

public class Person {
    private String name;
    private int age;

// 构造方法
public Person(String name, int age) {
    this.name = name;
    this.age = age;
}

// 成员方法:打印个人信息
public void printInfo() {
    System.out.println("姓名:" + name);
    System.out.println("年龄:" + age);
}

}

在这个例子中,Person类有两个私有的成员变量name和age。这些成员变量存储了每个Person对象的姓名和年龄信息。

成员变量在类中声明,在类的任何方法(如构造方法、成员方法等)之外。它们具有类范围的作用域,意味着它们可被同一类中的所有方法访问和使用。

4.成员方法

成员方法(Member Method)也称为实例方法(Instance Method),是定义在类中的操作或行为。它们用于访问和操作对象的属性,并执行特定的任务。每个对象都可以调用其所属类的成员方法。

下面是一个简单的例子,演示了一个名为Person的类和其中的成员方法:

public class Person {
    private String name;
    private int age;



// 构造方法
public Person(String name, int age) {
    this.name = name;
    this.age = age;
}

// 成员方法:获取姓名
public String getName() {
    return name;
}

// 成员方法:获取年龄
public int getAge() {
    return age;
}

// 成员方法:打印个人信息
public void printInfo() {
    System.out.println("姓名:" + name);
    System.out.println("年龄:" + age);
}
}


在这个例子中,Person类包含了两个私有属性name和age,以及构造方法和三个成员方法:getName、getAge和printInfo。getName和getAge方法用于获取对象的姓名和年龄属性值,而printInfo方法用于打印对象的姓名和年龄信息。

5.对象的实例化

一.对象实例化常用方式

方式一:直接new一个对象,最常用的一种。

方式二:反射,通过Class.forName("类的全限定名")。

方式三:构造器,通过Class.forName("类的全限定名"),再获取构造方法。

方式四:序列化,通过java.io.ObjectInputStream对象流的方式。

备注:工厂模式实例化、克隆实例化两种比较少用。

1.new一个对象

声名一个对象
public class NewObject {

/** 测试方法 */
public void print() {
System.out.println("NewObject print-------");
}
}
实例化

NewObject newObject = new NewObject();
newObject.print();

2.反射

声明一个对象

public class NewObject {

/** 测试方法 */
public void print() {
System.out.println("NewObject print-------");
}
}
实例化

Class<?> cla = Class.forName("com.oysept.instance.NewObject"); // 包名+类名
NewObject newObject = (NewObject) cla.newInstance(); // 实例化
newObject.print(); // 调用测试方法

3.构造器

声明一个对象

public class NewObject {

public NewObject() {
System.out.println("构造器1-------");
}

public NewObject(Object str) {
System.out.println("构造器2-------");
}

public NewObject(String str, Integer s) {
System.out.println("构造器3-------");
}

/** 测试方法 */
public void print() {
System.out.println("NewObject print-------");
}
}
场景一:无参构造方法

Class<?> cla = Class.forName("com.oysept.instance.NewObject"); // 包名+类名
			
// 场景一: 无参构造方法
Constructor<?> constructor = cla.getConstructor(); // 构造器
NewObject newObject = (NewObject) constructor.newInstance(); // 获取无参构造方法实例
newObject.print(); // 调用测试方法

场景二:带Object参数的构造方法

Class<?> cla = Class.forName("com.oysept.instance.NewObject"); // 包名+类名
			
// 场景二: 带Object参数的构造方法
Constructor<?> constructor = cla.getConstructor(Object.class);
NewObject newObject = (NewObject) constructor.newInstance("Object");
newObject.print(); // 调用测试方法

场景三: 带String和Integer参数的构造方法

Class<?> cla = Class.forName("com.oysept.instance.NewObject"); // 包名+类名
			
// 场景三: 带String和Integer参数的构造方法
Constructor<?> constructor = cla.getConstructor(String.class, Integer.class);
NewObject newObject = (NewObject) constructor.newInstance("String", 0);
newObject.print(); // 调用测试方法
4.序列化

声明一个对象,必须继承java.io.Serializable接口,才能序列化

import java.io.Serializable;

public class NewObject implements Serializable {
	

/**

 * */
   private static final long serialVersionUID = 1L;

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

}

序列化方法

/** 序列化 */
public static void serializable(Object obj, String file) {
    ObjectOutputStream objectOutputStream = null;
    try {
        objectOutputStream = new ObjectOutputStream(new FileOutputStream(new File(file)));
        objectOutputStream.writeObject(new NewObject());
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        try {
            if (objectOutputStream != null) {
                objectOutputStream.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

反序列化方法

/** 反序列化 */
public static Object unSerializable(String file) {
    Object obj = null;
    ObjectInputStream objectInputStream = null;
    try {
        objectInputStream = new ObjectInputStream(new FileInputStream(new File(file)));
        obj = objectInputStream.readObject();
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    } finally {
        try {
            if (objectInputStream != null) {
                objectInputStream.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    return obj;
}

序列化实例测试

public static void main(String[] args) {
    try {
        String file = "D:\\object.object"; // 对象存放地址
        // 先序列化
        serializable(new NewObject(), file);
			

​    // 再反序列化
​    NewObject new4 = (NewObject) unSerializable(file);
​    new4.print(); // 调用测试方法
} catch (Exception e) {
​    e.printStackTrace();
}

}

6.对象的使用

对象被创建之后,就可以使用该对象。通过运算符“.”,对象可以实现对自己变量的访问和方法的调用。

对象对自己变量访问的语法格式如下:

对象名.变量名;

对象对自己方法调用的语法格式如下:

对象名.方法名([参数值列表]);

【例1】对象的创建与使用

package graph;
public class Application1 {
	public static void main(String[] args) {
		Rectangle rectangle1;  //对象声明
		rectangle1=new Rectangle(4.5,2.0);//对象实例化
		double length=rectangle1.length;  //访问对象的变量length
		double width=rectangle1.width;    //访问对象的变量width
		double area=rectangle1.getArea(); //调用对象的方法getArea
		System.out.println("length="+length+",width="+width+",area="+area);
	}
}

​ 在Java中,null表示应用没有指向任何对象,运行过程中系统如果发现使用了这样一个引用时,会产生程序运行异常。例如,下面程序在运行时由于的rectangle1值为null而引发一NullPointerException异常。

package graph;

public class Application1 {

static Rectangle rectangle1; 

public static void main(String[] args) {

​     System.out.println(rectangle1.length);

}

}

7.对象的销毁

对象使用完之后需要对其进行清除。对象的清除是指释放对象占用的内存。在创建对象时,用户必须使用 new 操作符为对象分配内存。不过,在清除对象时,由系统自动进行内存回收,不需要用户额外处理。

Java 语言的内存自动回收称为垃圾回收(Garbage Collection)机制,简称 GC。垃圾回收机制是指 JVM 用于释放那些不再使用的对象所占用的内存。

Java 语言并不要求 JVM 有 GC,也没有规定 GC 如何工作。不过常用的 JVM 都有 GC,而且大多数 GC 都使用类似的算法管理内存和执行回收操作。

一个对象被当作垃圾回收的情况主要如下两种。
1)对象的引用超过其作用范围。

{
Object o = new Object(); // 对象o的作用范围,超过这个范围对象将被视为垃圾
}
1
2
3
2)对象被赋值为 null。

{
Object o = new Object();
o = null; // 对象被赋值为null将被视为垃圾
}
1
2
3
4
在 Java 的 Object 类中还提供了一个 protected 类型的 finalize() 方法,因此任何 Java 类都可以覆盖这个方法,在这个方法中进行释放对象所占有的相关资源的操作。

在 Java 虚拟机的堆区,每个对象都可能处于以下三种状态之一。

1 . 可触及状态:当一个对象被创建后,只要程序中还有引用变量引用它,那么它就始终处于可触及状态。

2 . 可复活状态:当程序不再有任何引用变量引用该对象时,该对象就进入可复活状态。在这个状态下,垃圾回收器会准备释放它所占用的内存,在释放之前,会调用它及其他处于可复活状态的对象的 finalize() 方法,这些 finalize() 方法有可能使该对象重新转到可触及状态。

3 . 不可触及状态:当 Java 虚拟机执行完所有可复活对象的 finalize() 方法后,如果这些方法都没有使该对象转到可触及状态,垃圾回收器才会真正回收它占用的内存。

8.匿名对象

匿名对象:没有名字的对象。
格式如下:

new Person().showMessage();
1

当然,你也可以通过Person创建一个实例对象后,再去调用Person类中的方法,具体如下:

Person p = new Person(); //创建对象p.
 
//给对象的各个属性赋值。
p.name = "蛋蛋";
p.age = 6;
p.height = 1.1;
 
//调用类中的方法
p.showMessage();
123456789

匿名对象的使用场景:

(1)类中的方法仅被对象调用一次。

new Person().showMessage();	 //showMessage方法被对象调用一次的时候.
1

(2)匿名对象做实参传递。

Person.show(new Person());      //匿名对象做实际参数。
1

匿名对象与非匿名对象对属性赋值的区别:

首先,看下面的代码,你感觉两者之间的区别是什么?

//非匿名对象
Person p = new Person();
p.name = "蛋蛋";
p.age = 6;
p.height = 1.1;
		
 
//匿名对象
new Perosn.name = "花花";
new Perosn.age = 21;
new Perosn.height = 1.2;
1234567891011

两者的最大区别:非匿名对象只是给对象p的三个属性赋值;匿名对象在给三个匿名对象的不同属性(单个属性)赋值。

posted @ 2024-08-01 10:52  白11  阅读(67)  评论(0)    收藏  举报