【Java基础】——面向对象:封装

简介: 【Java基础】——面向对象:封装

面向对象学习的 三条主线:

1.Java类及类的成员:属性、方法、构造器;代码块、内部类。

2.面向对象的大特征:封装性、继承性、多态性、(抽象性)。

3.其它关键字:this、super、static、final、abstract、interface、package、import等。


一、类和对象


Java类及类的成员:属性、方法、构造器;代码块、内部类


1、面向对象中两个重要的概念:


类:对一类事物的描述,是抽象的、概念上的定义

对象:是实际存在的该类事物的每个个体,因而也称为实例(instance)


面向对象程序设计的重点是类的设计


设计类,就是设计类的成员。


2、完成一个项目(或功能)的思路:


根据问题需要,选择问题所针对的现实世界中的实体。

从实体中寻找解决问题相关的属性和功能,这些属性和功能就形成了概念世界中的类。把抽象的实体用计算机语言进行描述,形成计算机世界中类的定义。即借助某种程序语言,把类构造成计算机能够识别和处理的数据结构。

将类实例化成计算机世界中的对象。对象是计算机世界中解决问题的最终工具。


3、二者的关系


对象,是由类new出来的,派生出来的。


4、面向对象思想落地实现的规则


1.创建类,设计类的成员。

2.创建类的对象。

3.通过“对象.属性”或“对象.方法”调用对象的结构。


补充:几个概念的使用说明

属性 = 成员变量 = field = 域、字段

方法 = 成员方法 = 函数 = method

创建类的对象 = 类的实例化 = 实例化类


5、对象的创建及内存解析


典型代码:


创建对象语法: 类名 对象名 = new 类名();


Person p1 = new Person();
Person p2 = new Person();
Person p3 = p1;//没有新创建一个对象,共用一个堆空间中的对象实体。


说明:如果创建了一个类的多个对象,则每个对象都独立的拥有一套类的属性。(非static的)

意味着:如果我们修改一个对象的属性a,则不影响另外一个对象属性a的值。

内存解析:


2e79b34518e94fc8aea77bb87809bc28.png


二、类的结构:属性、方法、构造器


1、属性


语法格式: 修饰符 数据类型 属性名 = 初始化值 ;


对比:属性 vs 局部变量

相同点:


定义变量的格式:数据类型 变量名 = 变量值。

先声明,后使用。

变量都其对应的作用域 。

不同点:

1、在类中声明的位置的不同


属性:直接定义在类的一对{}内

局部变量:声明在方法内、方法形参、代码块内、构造器形参、构造器内部的变量

2、关于权限修饰符的不同


属性:可以在声明属性时,指明其权限,使用权限修饰符。

常用的权限修饰符:private、public、缺省、protected —>封装性

局部变量:不可以使用权限修饰符。

3、默认初始化值的情况:


属性:类的属性,根据其类型,都默认初始化值。

整型(byte、short、int、long:0)

字符型(char:0 (或’\u0000’))

布尔型(boolean:false)

引用数据类型(类、数组、接口:null)

局部变量:没默认初始化值。

意味着,我们在调用局部变量之前,一定要显式赋值。

特别地:形参在调用时,我们赋值即可。


4、在内存中加载的位置:


属性:加载到堆空间中 (非static)

局部变量:加载到栈空间

在方法体外,类体内声明的变量称为成员变量。

在方法体内部声明的变量称为局部变量。


ebf043f1fa2b48a7890903a80f93726e.png

ceb3b33639c048b283834cb4c9f3e4ba.png

2、方法


2.1、方法的定义


方法是类或对象行为特征的抽象,用来完成某个功能操作。在某些语言中
也称为函数或过程。


将功能封装为方法的目的是,可以实现代码重用,简化代码。

Java里的方法不能独立存在,所有的方法必须定义在类里。

比如:Math类:sqrt()\random() …

Scanner类:nextXxx() …

Arrays类:sort() \ binarySearch() \ toString() \ equals() \ …


86e499284b1a478d9d993cf8fb772442.png

2.2、方法的重载


在同一个类中,允许存在一个以上的同名方法,只要它们的参数个数或者参数

类型不同即可。


重载的特点:


与返回值类型无关,只看参数列表,且参数列表必须不同。 (参数个数或参数类

型)。调用时, 根据方法参数列表的不同来区别。


重载示例:


//返回两个整数的和

int add(int x,int y){return x+y;}

//返回三个整数的和

int add(int x,int y,int z){return x+y+z;}

//返回两个小数的和

double add(double x,double y){return x+y;}


public class PrintStream {
    public static void print(int i) {……}
    public static void print(float f) {……}
    public static void print(String s) {……}
    public static void main(String[] args) {
        print(3);
        print(1.2f);
        print("hello!");
    }
}


2.3、可变个数的形参


JavaSE 5.0 中提供了Varargs(variable number of arguments)机制,允许直接定

义能和多个实参相匹配的形参。从而,可以用一种更简单的方式,来传递个数可

变的实参。


//JDK 5.0以前: 采用数组形参来定义方法,传入多个同一类型变量
public static void test(int a ,String[] books);
//JDK5.0: 采用可变个数形参来定义方法,传入多个同一类型变量
public static void test(int a ,String…books);


举例:


  public void test(String[] msg){
        System.out.println(“含字符串数组参数的test方法 ");
    }
    public void test1(String book){
        System.out.println(“****与可变形参方法构成重载的test1方法****");
    }
    public void test1(String ... books){
        System.out.println("****形参长度可变的test1方法****");
    }
    public static void main(String[] args){
        TestOverload to = new TestOverload();
//下面两次调用将执行第二个test方法
        to.test1();
        to.test1("aa" , "bb");
//下面将执行第一个test方法
        to.test(new String[]{"aa"});
    }


2.4、方法参数的值传递机制


方法,必须由其所在类或对象调用才有意义。若方法含有参数:


形参:方法声明时的参数。


实参: 方法调用时实际传给形参的参数值。


public class ValueTransferTest {
  public static void main(String[] args) {
    System.out.println("***********基本数据类型:****************");
    int m = 10;
    int n = m;
    System.out.println("m = " + m + ", n = " + n);
    n = 20;
    System.out.println("m = " + m + ", n = " + n);
    System.out.println("***********引用数据类型:****************");
    Order o1 = new Order();
    o1.orderId = 1001;
    Order o2 = o1;//赋值以后,o1和o2的地址值相同,都指向了堆空间中同一个对象实体。
    System.out.println("o1.orderId = " + o1.orderId + ",o2.orderId = " +o2.orderId);
    o2.orderId = 1002;
    System.out.println("o1.orderId = " + o1.orderId + ",o2.orderId = " +o2.orderId);
  }
}
class Order{
  int orderId;
}


基本数据类型:*****


m = 10, n = 10

m = 10, n = 20


引用数据类型:*****


o1.orderId = 1001,o2.orderId = 1001

o1.orderId = 1002,o2.orderId = 1002


Java的实参值如何传入方法呢?


Java里方法的参数传递方式只有一种: 值传递。 即将实际参数值的副本(复制品)传入方法内,而参数本身不受影响。

形参是基本数据类型:将实参基本数据类型变量的“数据值”传递给形参。

形参是引用数据类型:将实参引用数据类型变量的“地址值”传递给形参。


3、构造器


语法格式:

修饰符 类名 (参数列表) {

初始化语句;

}


3.1、构造器的特征


  • 它具有与类相同的名称
  • 它不声明返回值类型。(与声明为void不同)
  • 不能被static、 final、 synchronized、 abstract、 native修饰,不能有return语句返回值

3.2、构造器的作用:


创建对象;给对象进行初始化。

如: Order o = new Order(); Person p = new Person(“Peter”,15);

如同我们规定每个“人”一出生就必须先洗澡,我们就可以在“人” 的构造器中加入完成“洗澡”的程序代码,于是每个“人”一出生就会自动完成“洗澡”,程序就不必再在每个人刚出生时一个一个地告诉他们要“洗澡”了。


public class Animal {
    private int legs;
    // 构造器
    public Animal() {
        legs = 4;
    }
    public void setLegs(int i) {
        legs = i;
    }
    public int getLegs() {
        return legs;
    }
}


创建Animal类的实例: Animal a = new Animal(); 调用构造器, 将legs初始化为4。


根据参数不同,构造器可以分为如下两类:


隐式无参构造器(系统默认提供)

显式定义一个或多个构造器(无参、有参)

注意:


Java语言中,每个类都至少有一个构造器。

默认构造器的修饰符与所属类的修饰符一致。

一旦显式定义了构造器, 则系统不再提供默认构造器。

一个类可以创建多个重载的构造器。

父类的构造器不可被子类继承。


3.3、构造器重载


构造器一般用来创建对象的同时初始化对象。如


class Person{
  String name;
  int age;
  public Person(String n , int a){ name=n; age=a;}
} 


构造器重载使得对象的创建更加灵活,方便创建各种不同的对象。

构造器重载举例:


public class Person{
public Person(String name, int age, Date d) {this(name,age);…}
public Person(String name, int age) {…}
public Person(String name, Date d) {…}
public Person(){…}
}


构造器重载,参数列表必须不同。


三、封装与隐藏


我们程序设计追求“高内聚,低耦合”。

高内聚 :类的内部数据操作细节自己完成,不允许外部干涉;

低耦合 : 仅对外暴露少量的方法用于使用。


隐藏对象内部的复杂性,只对外公开简单的接口。便于外界调用,从而提

高系统的可扩展性、可维护性。通俗的说, 把该隐藏的隐藏起来,该暴露

的暴露出来。 这就是封装性的设计思想。


1、信息的封装和隐藏


Java中通过将数据声明为私有的(private), 再提供公共的( public)

方法:getXxx()和setXxx()实现对该属性的操作, 以实现下述目的:


隐藏一个类中不需要对外提供的实现细节;

使用者只能通过事先定制好的方法来访问数据, 可以方便地加入控制逻辑,

限制对属性的不合理操作;

便于修改, 增强代码的可维护性。


public class AnimalTest {
  public static void main(String[] args) {
    Animal a = new Animal();
    a.name = "大黄";
//    a.age = 1;
//    a.legs = 4;//The field Animal.legs is not visible
    a.show();
//    a.legs = -4;
//    a.setLegs(6);
    a.setLegs(-6);
//    a.legs = -4;//The field Animal.legs is not visible
    a.show();
    System.out.println(a.name);
  }
}
class Animal{
  String name;
  private int age;
  private int legs;//腿的个数
  //对属性的设置
  public void setLegs(int l){
    if(l >= 0 && l % 2 == 0){
      legs = l;
    }else{
      legs = 0;
//      抛出一个异常(暂时没有讲)
    }
  }
  //对属性的获取
  public int getLegs(){
    return legs;
  }
  public void eat(){
    System.out.println("动物进食");
  }
  public void show(){
    System.out.println("name = " + name + ",age = " + age + ",legs = " + legs);
  }
  //提供关于属性age的get和set方法
  public int getAge(){
    return age;
  }
  public void setAge(int a){
    age = a;
  }
}


2、四种访问权限修饰符


Java权限修饰符public、 protected、 (缺省)、 private置于类的成员定义前,用来限定对象对该类成员的访问权限。


397045d489b34910801991497b7a284f.png


对于class的权限修饰只可以用public和default(缺省)。


  • public类可以在任意地方被访问。
  • default类只可以被同一个包内部的类访问。

本系列文章参考尚硅谷课程。

目录
相关文章
|
2月前
|
安全 Java 编译器
Java的封装详解
封装和多态是面向对象编程(OOP)的重要概念。封装通过私有属性和公共方法实现数据隐藏和保护,使类的内部细节对外部不可见;多态则通过方法重载和重写实现同一方法在不同对象上的不同表现形式,增强了代码的灵活性和可维护性。两者结合使用,可以使Java程序更加安全、灵活且易于维护。
|
2月前
|
Java
Java的封装详解
封装是Java中实现数据隐藏和保护的核心机制。它通过将对象的状态和行为结合并限制外部直接访问,确保类的内部细节对外不可见,仅能通过公共方法访问和修改对象状态。封装带来了数据隐藏、提高代码可维护性和增强安全性等好处。在Java中,封装主要通过将属性设为私有并提供getter和setter方法来实现。这种方式不仅保护了数据完整性,还允许在修改类内部实现时不影响外部代码,从而提升程序的健壮性和可读性。
|
21天前
|
Java 关系型数据库 数据库
面向对象设计原则在Java中的实现与案例分析
【10月更文挑战第25天】本文通过Java语言的具体实现和案例分析,详细介绍了面向对象设计的五大核心原则:单一职责原则、开闭原则、里氏替换原则、接口隔离原则和依赖倒置原则。这些原则帮助开发者构建更加灵活、可维护和可扩展的系统,不仅适用于Java,也适用于其他面向对象编程语言。
14 2
|
2月前
|
Java 编译器
封装,继承,多态【Java面向对象知识回顾①】
本文回顾了Java面向对象编程的三大特性:封装、继承和多态。封装通过将数据和方法结合在类中并隐藏实现细节来保护对象状态,继承允许新类扩展现有类的功能,而多态则允许对象在不同情况下表现出不同的行为,这些特性共同提高了代码的复用性、扩展性和灵活性。
封装,继承,多态【Java面向对象知识回顾①】
|
2月前
|
SQL Java 编译器
Java——类与对象(封装)
封装是面向对象编程中的概念,指将数据(属性)和相关操作(方法)组合成独立单元(类),使外部无法直接访问对象的内部状态,只能通过提供的方法进行交互,从而保护数据安全。例如,手机将各种组件封装起来,只暴露必要的接口供外部使用。实现封装时,使用`private`关键字修饰成员变量,并提供`get`和`set`方法进行访问和修改。此外,介绍了包的概念、导入包的方式及其注意事项,以及`static`关键字的使用,包括静态变量和方法的初始化与代码块的加载顺序。
45 10
Java——类与对象(封装)
|
2月前
|
安全 Java 数据安全/隐私保护
Java 封装怎么理解
封装是Java中的一种重要机制,它将对象的状态(数据)和行为(方法)打包在一起并控制外部访问权限,以保护数据不被随意修改。封装的主要目的包括数据保护、接口设计和增强模块性。通过使用`private`、`protected`及`public`等访问控制修饰符,结合getter和setter方法,可以有效隐藏对象内部实现细节。下面是一个简单的`BankAccount`类示例,展示了如何通过封装保护类的内部状态,确保数据安全和一致性,简化类的使用。理解封装有助于编写高质量代码和设计优秀程序架构。
|
2月前
|
Java
java中面向过程和面向对象区别?
java中面向过程和面向对象区别?
35 4
|
2月前
|
Java 数据安全/隐私保护
Java 封装详解
在 Java 中,封装是面向对象编程的关键特性,通过将对象的状态(数据)和行为(方法)结合并利用访问控制保护数据,防止外部随意访问和修改。主要特点包括访问控制(如 `private` 和 `protected`)、数据隐藏及方法暴露(如 getter 和 setter)。封装的优点在于保护数据、隐藏实现细节、易于维护以及提高代码可读性。下面是一个简单的 `Person` 类封装示例,展示了如何通过 getter 和 setter 控制对类内部状态的访问,并进行合法性检查。总结而言,封装有助于构建清晰、易用且可维护的代码结构,是编写高质量 Java 程序的重要原则。
|
2月前
|
安全 Java 开发者
Java修饰符与封装:理解访问权限、行为控制与数据隐藏的重要性
Java中的修饰符和封装概念是构建健壯、易维护和扩展的Java应用程序的基石。通过合理利用访问权限修饰符和非访问修饰符,开发者能够设计出更加安全、灵活且高效的代码结构。封装不仅是面向对象编程的核心原则之一,也是提高软件项目质量和可维护性的关键策略。
20 1
|
2月前
|
Java
接口和抽象类【Java面向对象知识回顾②】
本文讨论了Java中抽象类和接口的概念与区别。抽象类是不能被实例化的类,可以包含抽象和非抽象方法,常用作其他类的基类。接口是一种纯抽象类型,只包含抽象方法和常量,不能被实例化,且实现接口的类必须实现接口中定义的所有方法。文章还比较了抽象类和接口在实现方式、方法类型、成员变量、构造方法和访问修饰符等方面的不同,并探讨了它们的使用场景。
接口和抽象类【Java面向对象知识回顾②】