Notes
Java
对象

面向过程和面向对象

面向过程

以具体的求解过程为研究和实现的主体,过程完备。如C语言。
缺点:无法将复杂的系统描述清楚,很难满足现在对软件规模和复杂度的需求。

面向对象

以求解问题中所涉及的各种对象为主体,力图求解过程符合人们日常的思维习惯,降低了求解问题的难度和复杂性,提高了编程的效率,比如C++,Java语言。

面向对象的基本特征

封装
将数据(属性)和对数据的操作(功能)封装在一起。成员变量,成员方法,类.
继承
子类可以继承父类的属性和功能,同时又可以增加子类独有的属性和功能。
多态
多个操作具有相同的名字,但是接受的消息类型必须不同。
同一个操作被不同类型的对象调用时产生不同的行为。

类和对象

类的基本结构

class 机动车    // 类声明
{   
    // 成员变量
    int speed;
    float height;
    float weight;
    // 成员方法
    void changSpeed(int newSpeed)
    {    speed=newSpeed;    }
    float getWeight()
    {    return weight;   }
    float getHeight()
    {    return height;   }
}

构造方法

  • 类创建对象时,需要使用构造方法完成对象的初始化工作。
  • 构造方法的名称必须与类名相同。
  • 构造方法没有返回值
  • 一个类中可以有若干个构造方法(名称相同),但是构造方法的参数必须不同。
  • 如果类中没有构造方法,系统为类定义一个默认的构造方法,该构造方法没有参数,类体为空。
class Rect
{
    double sideA,sideB;
    Rect( ){  }  //无参构造方法
    Rect(double a, double b){ //有参构造方法,初始化对象的两个属性
        sideA=a; 
        sideB=b; 
    }
    double computeArea( ){
        return sideA*sideB; 
    }
    double computeGirth( ){
        return (sideA+sideB)*2; 
    }
}

对象的创建和使用

对象声明

类的名字 对象名字

Rect rectangleOne;
rectangleOne 是一个空对象,它不能访问成员变量和成员方法

对象的创建

对象名=new 构造方法名(参数列表)

rectangleOne=new Rect( );
rectangleOne=new Rect(10, 20);
rectangleTwo=new Rect(33, 66);
 
//也可以把声明对象和创建对象合在一起进行
Rect rectangleOne=new Rect(10,20);

对象的使用

对象名.成员变量名
对象名.成员方法名(参数列表)

rectangleOne.sideA=10;
rectangleOne.sideB=20;
rectangleOne.computeArea( );
rectangleOne.computeGirth( );

成员变量

实例变量

不用关键字 static 修饰。
一个类中不同对象的实例变量将被分配不同的存储空间。
只能通过对象访问实例变量。

静态变量(类变量)

用关键字 static 修饰。
一个类中所有对象的某个静态变量被分配同一个内存,所有对象共享这个静态变量
可以通过类名访问静态变量,也可以通过某个对象访问静态变量。

class Circle
{
    static double pi; //类变量
    double radius;   //实例变量
}
Circle.pi=3.14;
Circle circle1=new Circle();
circle1.radius=10;
Circle circle2=new Circle();
circle2.radius=100;

1

在上面的代码中, Pi 作为公共的区域,所有对象共享一个内存。

常量

final 成员变量
如果一个成员变量修饰为final,就是常量。常量的名字习惯用大写字母。

final int MAX=100;

:::tip 如果final变量是简单类型,则其值不能发生变化
如果final变量是复合类型,则其指向对象的引用不能发生变化
:::

类的封装

封装:将类的属性和方法封装在一个类中,对外提供一个统一的接口,隐藏类的内部实现细节。在定义一个类时,我们可以把它的属性私有化,使用 private 修饰。让这个属性只能在类中被访问,当外部需要访问或设置这个属性时,我们可以提供一个公共的方法来访问这个属性。

class Person
{
    private String name; //私有属性
    public String getName( ){ //公共方法
        return name;
    }
    public void setName(String name){ //公共方法
        this.name=name;
    }
}

利用这个方法,我们可以对外部传入的参数进行验证,保证数据的准确性和安全性。比如下面的例子中,我们对外部传入的年龄进行了验证,如果年龄小于0或者大于150,就抛出一个异常。

class Person
{
    private int age;
    public int getAge( ){
        return age;
    }
    public void setAge(int age){
        if(age<0 || age>150){
            throw new RuntimeException("年龄不合法");
        }
        this.age=age;
    }
}

构造方法

构造方法是一个特殊的方法,它在对象创建时被调用。如果一个类中没有定义构造方法,那么编译器会自动为这个类添加一个无参的构造方法。如果需要在对象创建时对对象属性进行初始化,就需要定义构造方法。

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

还有一种构造方法,就是无参构造方法

class Person
{
    private String name;
    private int age;
    public Person( ){ //无参构造方法
        this.name="张三";
        this.age=20;
    }
}

构造方法是可以被重载的,也就是说,一个类中可以有多个构造方法。

class Person
{
    private String name;
    private int age;
    public Person( ){ //无参构造方法
        this.name="张三";
        this.age=20;
    }
    public Person(String name,int age){ //有参构造方法
        this.name=name;
        this.age=age;
    }
}

在上面的代码中,当我们创建一个对象时,可以使用无参构造方法,也可以使用有参构造方法。使用无参构造方法时,对象的属性会被初始化为默认值。

Person p1=new Person( ); //使用无参构造方法
Person p2=new Person("李四",30); //使用有参构造方法

this 关键字

Java 中的 this 关键字是一个引用,它指向当前对象。

class Person
{
    private String name;
    private int age;
    public Person( ){
        this.name="张三";
        this.age=20;
    }
    public Person(String name,int age){
        this.name=name;
        this.age=age;
    }
    public void print( ){
        // this.name 等价于 name
        // highlight-start
        System.out.println("姓名:"+this.name+",年龄:"+this.age);
        // highlight-end
    }
}

this 关键字也可以用来调用当前类中的其他方法。

class Person
{
    private String name;
    private int age;
    public Person( ){
        this.name="张三";
        this.age=20;
    }
    public Person(String name,int age){
        this.name=name;
        this.age=age;
    }
    public void print( ){
        System.out.println("姓名:"+this.name+",年龄:"+this.age);
    }
    public void printInfo( ){
        // highlight-start
        this.print( );
        // highlight-end
    }
}

构造方法之间可以通过 this 关键字来调用。

class Person
{
    private String name;
    private int age;
    public Person( ){
        this.name="张三";
        this.age=20;
    }
    public Person(String name,int age){
        this.name=name;
        this.age=age;
    }
    public Person(String name){
        // highlight-start
        // 调用两个参数的构造方法
        this(name,20);
        // highlight-end
    }
    public void print( ){
        System.out.println("姓名:"+this.name+",年龄:"+this.age);
    }
}

垃圾回收

Java 中的垃圾回收是自动的,不需要程序员手动去释放内存。但是我们也可以通过 System.gc( ) 方法来强制垃圾回收。

class Person
{
    private String name;
    private int age;
    public Person( ){
        this.name="张三";
        this.age=20;
    }
    public Person(String name,int age){
        this.name=name;
        this.age=age;
    }
    public void print( ){
        System.out.println("姓名:"+this.name+",年龄:"+this.age);
    }
    public void finalize( ){
        System.out.println("对象被回收了");
    }
}

在上面的代码中,我们重写了 finalize( ) 方法,当对象被回收时,会调用该方法。

Person p=new Person( );
p=null;
System.gc( );

static 关键字

静态变量

当多个对象共享同一个属性时,可以将该属性定义为静态变量。

class Person
{
    // highlight-start
    // 静态变量
    private static String country="中国";
    // highlight-end
    private String name;
    private int age;
    public Person( ){
        this.name="张三";
        this.age=20;
    }
    public Person(String name,int age){
        this.name=name;
        this.age=age;
    }
    public void print( ){
        System.out.println("姓名:"+this.name+",年龄:"+this.age+",国家:"+country);
    }
}

为静态变量赋值时,可以通过类名来访问。

Person.country="美国";

static只能修饰成员变量,不能修饰局部变量。它是非法的。

class Person
{
    public void print( ){
        // highlight-start
        // 非法的
        static int a=10;
        // highlight-end
    }
}

静态方法

当多个对象共享同一个方法时,可以将该方法定义为静态方法。

class Person
{
    private String name;
    private int age;
    public Person( ){
        this.name="张三";
        this.age=20;
    }
    public Person(String name,int age){
        this.name=name;
        this.age=age;
    }
    public void print( ){
        System.out.println("姓名:"+this.name+",年龄:"+this.age);
    }
    // highlight-start
    // 静态方法
    public static void printInfo( ){
        System.out.println("这是一个静态方法");
    }
    // highlight-end
}

静态代码块

静态代码块是在类加载时执行的,只执行一次。

class Person
{
    // highlight-start
    // 静态代码块
    static{
        System.out.println("这是一个静态代码块");
    }
    // highlight-end
    //...
}

在主函数调用时,静态代码块会先执行。

public class Main
{
    public static void main(String[] args)
    {
        // highlight-start
        // 静态代码块会先执行
        // 声明 Person 对象
        Person p=new Person( );
        // highlight-end
    }
}

内部成员类

内部成员类是定义在类中的类,它可以访问外部类的所有成员,包括私有成员。

class Person
{
    private String name;
    private int age;
    public Person( ){
        this.name="张三";
        this.age=20;
    }
    public Person(String name,int age){
        this.name=name;
        this.age=age;
    }
    public void print( ){
        System.out.println("姓名:"+this.name+",年龄:"+this.age);
    }
    // highlight-start
    // 内部成员类
    class PersonInfo
    {
        public void print( ){
            System.out.println("姓名:"+Person.this.name+",年龄:"+Person.this.age);
        }
    }
    // highlight-end
}

如果希望调用内部成员类的方法,可以通过外部类的对象来调用。

Person p=new Person( );
Person.PersonInfo pi=p.new PersonInfo( );
pi.print( );