Java

java面向对象

2022-02-16  本文已影响0人  马佳乐

面向对象的概念

是对一组具有相同属性(或称状态,用数据表示)和行为(或称操作,用方法实现)的对象的抽象,一个类所包含的方法和数据描述了一组对象的共同属性和行为。对象则是类的具体化,是类的实例。
在面向对象的程序设计中,总是先声明类,再由类生成其对象,类是建立对象的“模板”,按照这个模板所建立的一个个具体的对象,就是类的实际例子,通常称为实例。编写程序,实际上是定义类,而真正用的是类的对象,这个过程称为类的实例化

面向对象程序的设计方法具有如下3个特点:

封装性:封装是一种信息隐蔽技术,通过类的说明实现封装,即将程序中数据和基于数据的操作方法封装起来,使之成为一个整体,其载体就是类,它是程序中的最小模块。这样可以保护数据和操作方法的安全,是对象的重要特性。
继承性:主要描述的是类与类之间的关系,通过继承,可以在无需重新编写原有类的情况下,对原有类的功能进行扩展。
多态性:一般类中定义的属性或方法,被子类继承之后,可具有不同的数据类型或不同的行为,这样,一个程序可以存在同名的不同方法,不同类的对象可以响应同名的方法,具体的实现方法却不同。多态性使得语言具有灵活性、抽象、行为共享和代码共享的优势,很好地解决了应用程序方法同名问题。

类是Java的核心,任何一个Java程序至少包含一个类,类中封装了数据和基于数据的操作,这种操作在Java类中称为方法。

类定义的格式

[public][abstract|final] class 类名{
    数据类型 成员变量1;
    ...
    数据类型 成员变量M;
    数据类型 成员方法名1(参数列表) { 方法体 }
    ...
    数据类型 成员方法名N(参数列表) { 方法体 }
}

public:定义类的访问权限,如果一个类被声明为public,则与其不在同一个包中的其它类可以通过引用它所在的包来使用这个类,否则这个类就只能被同一包中的其他类使用。
abstract:表示该类为抽象类,不能创建对象实例。
final:表示该类为最终类,不能再派生出新的子类。

成员变量的声明

成员变量的声明格式:
[访问控制修饰符][其它修饰符] 数据类型 变量名称;
在类的定义中,当一个变量的声明不属于任何方法时,则该变量为类的成员变量。成员变量描述了类和对象的状态(或属性)

class person{
    int age=0;  //年龄
    boolean gender; //性别
    String name; //姓名
    void setinfor(int x, boolean y, String z){
        age=x; gender=y; name=z;
    }
    ….//其它成员方法的定义
}

成员变量是类定义的一部分,成员变量可以是任何数据类型的数据

成员变量在定义时可赋初始值。若在定义成员变量时没有指明初始值,则默认如下:
数值型变量初始值为0
对象类变量初始值为null
布尔型为false

在同一类中,各成员变量不能同名
成员变量在整个类的定义中都有效,即类定义中的成员方法和成员变量都可以操作某个成员变量。

访问控制修饰符

public:公开的/公有的,只要能使用这个类,就可以直接存取这个变量的值。
protected:受限的/保护的,仅能被其子类或与其处于同一包的其他类直接存取。
private:私有的,除了声明它们的类外,不能被包括其子类在内的任何其他类直接存取。
默认情况:成员变量前不加访问控制符,则其只能被同一包中的类直接存取,即为包可见性。

成员方法的声明

成员方法的声明格式:

[访问控制修饰符][其它修饰符]  返回类型  方法名称(参数列表)
{
    方法体语句
}

成员方法也是类的一部分,大部分的类定义中都包含成员方法。成员方法的返回值可以是任何数据类型的数据。如果没有返回值,返回值类型写成void。
成员方法的参数列表是使用逗号隔开的参数,放在圆括号中,参数也可以是任何数据类型的数据,即使没有参数,圆括号也不可省略。

方法重载

同一类中的方法名可以相同,前提是名称相同的各方法之间在参数个数或参数类型等方面要存在差异。

类中的变量

分类 局部变量 成员变量
定义位置 方法体中和方法的参数列表 类属性定义部分所定义的
声明格式 方法体: 类型 变量名;方法参数列表:类型1 变量1,类型 变量2,…. [访问控制修饰符]类型 变量名
作用域 方法体内有效 无论何种访问权限,成员变量可在该类的所有方法中使用
初始化与赋值 不可自动初始化,要求在程序中显式地给其赋值,只有当方法被调用执行时,局部变量才被分配内存空间,调用完毕后,所占空间被释放。 可自动初始化,数值型为0,逻辑型为false,引用型为null.可在声明时进行,也可在方法中实现,但不能在声明和方法之间进行赋值

构造方法

构造方法是与类同名的特殊的成员方法。 Java中的每个类都有构造方法,在创建类对象时,系统将自动调用构造方法以初始化该类的一个新的对象(实现对数据成员的初始化)。
构造方法的定义格式:

         类名(形参列表)       
             {   方法体   }

main()方法

Java独立应用程序(Application程序)都从main开始执行,一个程序中只有一个main方法,其使用形式为:

  public static void main(String args[]){
   ……
   }

对象

对象的创建

对象是类的实例,类是对象的模板。
对象的创建:
格式1: 类名 变量名= new 构造方法(实参列表);
格式2:

类名  变量名;   //声明对象
变量名=new 构造方法(实参列表);  //创建对象

构造方法只能在创建对象时使用,创建完对象后不能再通过“对象.方法()”的方式来使用构造方法。
new 表达式确实返回了对新建对象的引用,但构造方法本身并没有任何返回值。
例如:求矩形面积

package test_java;
import java.util.Scanner;

public class hello {
    public static void main(String[] args) {
        Scanner sc=new Scanner(System.in);
        System.out.println("请输入矩形的宽");
        double w=sc.nextDouble();
        System.out.println("请输入矩形的高");
        double h=sc.nextDouble();
        Rect r=new Rect();
        r.height=h;
        r.width=w;
        r.area();   

    }

}
class Rect{
    double height;
    double width;
    void area(){
        System.out.println("面积="+height*width);
    }
}

对象的引用

对象的使用

对象的消亡

this关键字

Java中提供this关键字指代当前对象,用于在方法中访问对象的其他成员。其常用方法:
①通过this可以明确地去访问一个类的成员变量,解决与局部变量名冲突问题。

class person{
    int age;  //年龄
    boolean gender; //性别
    String name; //姓名
    void setinfor(int age, boolean gender, String name){
        this.age=age; 
        this.gender=gender; 
        this.name=name;
    }
    ….//其它成员方法的定义
}

②通过this调用成员方法,this可以省略不写。

class person{
    int age;  //年龄
    boolean gender; //性别
    String name; //姓名
    void setinfor(int age, boolean gender, String name){
        this.age=age; 
        this.gender=gender; 
        this.name=name;
    }
    int get_age(){  return this.age;    }   
    void show(){
        int x=this.get_age();
        System.out.println(“年龄为:”+x);
    }   
}

③在一个构造方法中使用this(参数列表)的形式调用其他的构造方法。

    public Person(){    System.out.println(“无参构造方法被调用了...”);     }
    public Person(int age){
        this();
        System.out.println(“有参构造方法被调用了”);
    }
}
public class Test{
    public static void main(String[] args){
        Person p=new Person(20);
    }
}

使用this调用类的构造方法时应注意:

访问权限

类的访问控制

类的访问控制修饰符只有public(公共类)及无修饰符(缺省类)两种。

类型 无修饰(缺省类) public(公共类)
同一包中的类
不同包中的类

一个Java源程序(扩展名为.java的文件)中只能有一个public类,因此,为了使一个包中饱含多个public类,可将一个Java程序拆分成几个程序,只要包的名称相同即可。

类成员的访问控制

类型 private public protected 无修饰
同一类
同一包中的子类
同一包中的非子类
不同包中的子类
不同包中的非子类

能对类访问,并不意味着能访问该类中的成员。即要访问类的成员,必须要求类可以访问且成员可访问。
当类可访问时,对不可直接访问的成员变量,可以通过可访问的方法来访问它。

static关键字

在Java中定义了一个static关键字,用于修饰类的成员,被static修饰的成员具备一些特殊性。

静态变量

成员变量可分为实例变量和静态变量

分类 实例变量 静态变量
声明 不使用关键字static 使用关键字static
内存空间分配 同一个类的不同对象的实例变量被分配不同的内存空间 类的静态成员变量由该类的所有对象共有,一个类对象的空间内不包含静态数据成员的空间,其所占的空间不会随对象的产生而分配,或随对象的撤销而消失。它是在类被加载时被分配的,即使没有创建类的一个对象。
初始化 在对象初始化时完成相应的初始化工作,并由某一个对象独自拥有 在类被加载时完成相应的初始化工作
作用域 某一个类具体创建的实例对象 整个类
访问方式 只能由对象调用 可由对象访问,也可直接由类名访问
class Student {
    static String schoolName="***大学"; // 定义静态变量schoolName
}
public class Example12 {
    public static void main(String[] args) {
        System.out.println("默认学校名称为:"+Student.schoolName);//默认学校名称为:***大学
        Student stu1 = new Student(); // 创建学生对象
        Student stu2 = new Student();
        Student.schoolName = "河北工业大学"; // 为静态变量赋值
        System.out.println("我的学校是" + stu1.schoolName); // 打印第一个学生对象的学校  我的学校是河北工业大学
        System.out.println("我的学校是" + stu2.schoolName); // 打印第二个学生对象的学校  我的学校是河北工业大学 
    }
}

静态方法

方法是类的动态属性。
对象的行为是由其方法来实现的。
格式:

[访问控制修饰符][其它修饰符]  返回类型  方法名称(参数列表)
{
    方法体语句
}

一定条件下,同一类中,不同的方法之间可以相互调用。
在方法声明时,通过修饰符可以对方法访问实施控制。在方法中,可以对类的成员变量进行访问,但不同类型的方法对不同类型的成员变量的访问是有限制的。
类中的方法可分为实例方法和静态方法

分类 实例方法 静态方法
声明 不使用关键字static 使用关键字static修饰
操作对象 静态变量和实例变量 静态变量
调用方式 只能由对象调用 可由对象调用,也可直接由类名调用
方法间的调用 可相互调用 只能调用静态方法,不能调用实例方法

在创建对象之前,实例变量没有分配内存,实例方法也没有入口地址。

静态代码块

在Java类中,使用一对大括号包围起来的若干行代码被称为一个代码块,也称为自由块。Java中的自由块分为两种:静态块和非静态块
静态块:用static关键字修饰的代码块称为静态代码块。
当类被加载时,静态代码块会执行,由于类只加载一次,因此静态代码块只执行一次,多个静态块的时候,按出现的顺序执行。
在程序中,通常会使用静态代码块来对类的成员变量进行初始化。

class Person{
    static{
        System.out.println(“Person的静态代码块执行了”);
    }
}

非静态块:未用static关键字修饰的代码块。
每次初始化一个对象,都会导致一次非静态块的执行;
在构造函数执行之前执行;
继承关系: 父类的非静态块->父类的构造函数->自己的自由块->自己的构造函数

 public class Test { 
    { 
        System.out.println("before"); 
    } 
 }

static导入

在通过import关键字导入包的时候可以加上static修饰符,则可导入包中的静态变量和静态方法,并且调用静态变量和静态方法的时候不需要类的点运算符操作,格式如下:
import static 包名.类名.*;
import static 包名.类名.成员变量;
import static 包名.类名.成员方法;
例如: import static java.lang.System.*;
则可以直接使用System类的静态方法和静态变量
例如:
out.println("hello");
这行代码相当于 System.out.println("hello");

方法调用中的数据传递

值传递

引用传递

方法的参数类型一般是复合类型(引用类型)。复合类型变量中存储的是对象的引用,所以在参数转送中是传送引用,方法接收参数的引用,因此任何对形参的改变都会影响到对应的实参。“引用的单向传送,数据的双向传送”。

返回值

实例变量和静态成员变量传递

实例变量和静态成员变量传递方式也不是在形参和实参之间传递数据,而是利用在类中定义的实例变量和静态成员变量是类中诸方法共享的变量的特点来传递数据。

垃圾回收

在Java中,当一个对象成为垃圾后仍会占用内存空间,时间一长,就会导致内存空间的不足,因此,Java中引入了垃圾回收机制,使得程序员不需要过多关心垃圾对象回收的问题,JVM会启动垃圾回收器将垃圾对象从内存中释放。

    class 类名{
        ……
        protected void finalize() throws Throwable
        {……}
    }

垃圾回收举例:

class Person {
    // 下面定义的finalize方法会在垃圾回收前被调用
    public void finalize() {
        System.out.println("对象将被作为垃圾回收...");
    }
}
public class Test {
    public static void main(String[] args) {
        // 下面是创建了两个Person对象
        Person p1 = new Person();
        Person p2 = new Person();
        // 下面将变量置为null,让对象成为垃圾
        p1 = null;
        p2 = null;
        // 调用方法进行垃圾回收
        System.gc();
    }
}

在以下三种情况将使用finalize
①所有对象被Garbage Collection时自动调用,比如运行System.gc()的时候。
②程序退出时为每个对象调用一次finalize方法。
③显式的调用finalize方法。

除此以外,正常情况下,当某个对象被系统收集为无用信息的时候,finalize()将被自动调用,但是JVM不保证finalize()一定被调用,也就是说,finalize()的调用是不确定的,这也就是为什么sun不提倡使用finalize()的原因。
如果在程序终止之前垃圾回收器始终没有执行垃圾回收操作,那么垃圾回收器将始终不会调用无用对象的finalize()方法。因为finalize()只有在垃圾回收器工作的时候才会被调用,也就是说,通过它进行资源释放并不能确保马上被释放,甚至可能根本不会被释放(因为垃圾回收器可能不会工作)。程序即使显式调用System.gc()或Runtime.gc()方法,也不能保证垃圾回收操作一定执行,因此不能保证无用对象的finalize()方法一定被调用。

上一篇下一篇

猜你喜欢

热点阅读