CodeGym /Java 博客 /随机的 /Java 类:编写自己的类、构造函数
John Squirrels
第 41 级
San Francisco

Java 类:编写自己的类、构造函数

已在 随机的 群组中发布
你好!今天我们将讨论Java中的类。您可以说类构成了 Java 编程的基石。当你成为一名程序员时,几乎你的全部工作就是编写你自己的具有各种功能的类。让我们看看这意味着什么以及它是如何工作的。:) 如您所知,Java 是一种面向对象的编程语言。所有程序都由以某种方式相互关联的对象组成。类本质上是对象的模板。它决定了对象的外观和功能。每个对象都是某个类的对象。考虑这个非常简单的例子:

public class Cat {

    String name;
    int age;

}
假设我们出于某种原因正在编写一个涉及猫的程序(例如,我们有一家兽医诊所提供在线帐户访问权限)。我们创建了一个Cat类,并在其中声明了两个变量:String nameint age。这些成员变量称为字段。从本质上讲,这是我们将来要创建的所有猫的模板。每个Cat对象都有两个变量:名称和年龄。

public class Cat {

    String name;
    int age;

    public static void main(String[] args) {
        Cat smudge = new Cat();
        smudge.age = 3;
        smudge.name = "Smudge";

        System.out.println("We created a cat named " + smudge.name + ". His age is " + smudge.age);
    }

}
这是它的工作原理!我们创建了一只猫,给它起名字和年龄,然后将其全部显示在控制台上。小菜一碟。:) 通常,类描述现实世界中的事物和现象。一只猫、一张桌子、一个人、一道闪电、一本书的一页、一个轮子——您将使用单独的类在您的程序中创建所有这些东西。现在,让我们关注我们在Cat类中声明的变量。它们被称为字段或实例变量。他们的名字真的说明了一切。Cat类的每个实例(或对象)都将具有这些变量。我们创建的每只猫都有自己的名字变量和年龄多变的。这是有道理的——真正的猫基本上就是这样。:) 除了实例变量,还有类变量(静态变量)。让我们完成我们的例子:

public class Cat {

    String name;
    int age;

    static int count = 0;

    public static void main(String[] args) {
        Cat smudge = new Cat();
        smudge.age = 3;
        smudge.name = "Smudge";
        count++;

        Cat fluffy = new Cat();
        fluffy.age = 5;
        fluffy.name = "Fluffy";
        count++;

        System.out.println("We created a cat named " + smudge.name + ". His age is " + smudge.age);
        System.out.println("We created a cat named " + fluffy.name + ". His age is " + fluffy.age);

        System.out.println("Total number of cats = " + count);
    }
}
控制台输出:我们创建了一只名为 Smudge 的猫。他的年龄是 3 我们创造了一只名叫 Fluffy 的猫。他的年龄是 5 猫的总数 = 2 现在我们班有一个新变量叫做 count。它负责计算创建的猫。每次我们在main中创建一只猫方法,我们将这个变量增加 1。这个变量是使用关键字 static 声明的。这意味着它属于类,而不属于类的特定对象。这当然是有道理的:每只猫的名字都属于那只特定的猫,但我们需要一个适用于所有猫的猫计数器。这正是关键字 static 所完成的:它使 count 变量成为所有猫的单个变量。注意:当我们显示变量时,我们没有使用 smudge.count 或 fluffy.count。它既不属于 Smudge 也不属于 Fluffy;它属于整个Cat类。这就是为什么它只是计数。您也可以编写 Cat.count。那也是正确的。当显示 name 变量时,我们不会执行以下操作:

public class Cat {

    String name;
    int age;

    static int count = 0;

    public static void main(String[] args) {
        Cat smudge = new Cat();
        smudge.age = 3;
        smudge.name = "Smudge";
        count++;

        System.out.println("We created a cat named " + name + ". His age is " + smudge.age);

        System.out.println("Total number of cats = " + count);
    }
}
这是一个错误!每只猫都有自己的名字。编译器在这里感到困惑。“向控制台输出一个名字?谁的名字?” :/“

方法

除了变量,每个类都有方法。我们将在单独的课程中更详细地讨论它们,但一般原则非常简单。方法定义了类的功能,即类的对象可以做什么。您已经熟悉其中一种方法:main()方法。但是,您可能还记得,main方法是静态的,这意味着它属于整个类(逻辑与变量相同)。但是,标准的非静态方法只能在我们创建的特定对象上调用。比如我们要写一个猫类,我们需要知道我们程序中的一只猫应该具备哪些功能。在此前提下,让我们为我们的猫写几个方法:

public class Cat {

    String name;
    int age;

    public void sayMeow() {
        System.out.println("Meow!");
    }

    public void jump() {
        System.out.println("Pounce!");
    }

    public static void main(String[] args) {
        Cat smudge = new Cat();
        smudge.age = 3;
        smudge.name = "Smudge";

        smudge.sayMeow();
        smudge.jump();

    }
}
一探究竟!现在我们班更像一只猫了!现在我们不只有一只有名字(“Smudge”)和年龄(3)的猫。他还会喵喵叫和跳跃!如果没有这种“功能”,它会是什么样的猫?:) 我们正在获取一个特定的对象(涂抹)并调用它的sayMeow()jump()方法。再看控制台:喵!猛扑!一只真正的猫!:)

创建自己的课程。抽象

将来,您将不得不编写自己的类。写的时候需要注意什么?如果我们谈论的是变量,那么您将需要使用一种称为抽象的东西。抽象是面向对象程序设计的四大基本原则之一。这意味着提取项目最重要和最重要的特征,相反,抛弃那些次要或无关紧要的特征。例如,让我们为公司员工创建一个文件柜。为了创建员工对象,我们编写了一个Employee班级。哪些特征是我们公司文件柜员工的重要描述符?姓名、出生日期、SSN 和员工 ID。但是我们不太可能需要员工的身高、眼睛颜色或头发颜色来作为公司的员工记录。公司不需要这些信息。因此,在Employee类中,我们声明了以下变量:String nameint ageint socialSecurityNumberint employeeId. 而且我们遗漏了不必要的信息(如眼睛颜色)。换句话说,我们创建了一个抽象。但是,如果我们为模特经纪公司制作文件柜,情况就会发生巨大变化。模特的身高、眼睛颜色和头发颜色是重要的特征,但她的 SSN 与我们绝对无关。因此,在Model类中,我们需要创建以下变量:String heightString hairString eyes。这就是抽象的工作原理——很简单!:)

构造器

让我们回到猫的例子。

public class Cat {

    String name;
    int age;

    public static void main(String[] args) {
        Cat smudge = new Cat();

        System.out.println("Here the program does something for 2 hours...");

        smudge.age = 3;
        smudge.name = "Smudge";

    }
}
查看这段代码并尝试找出我们的程序出了什么问题。我们的节目有一只没有名字或年龄的猫 2 小时!当然,这本质上是错误的。兽医诊所的数据库不应包括没有信息的猫。目前,我们的猫任由程序员摆布。我们相信他不会忘记指定姓名和年龄,一切都会好起来的。如果他忘记了,数据库就会出问题:未命名的猫。我们如何解决这个问题?我们必须以某种方式防止没有名字和年龄的猫被创造出来。这是构造函数来救援的地方。让我们举个例子:

public class Cat {

    String name;
    int age;

    // Constructor for the Cat class
    public Cat(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public static void main(String[] args) {

        Cat smudge = new Cat("Smudge", 5);
    }
}
本质上,构造函数是类对象的模板。在这种情况下,我们指出必须为每个cat对象指定两个参数,一个String和一个int。如果我们现在尝试创建一只无名猫,那是行不通的。

public class Cat {

    String name;
    int age;

    public Cat(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public static void main(String[] args) {

        Cat smudge = new Cat(); // Error!
    }
}
现在类有了构造函数,Java 编译器就知道对象应该是什么样子,并且不允许在不指定参数的情况下创建对象。现在,让我们研究一下您在构造函数中看到的关键字 this。这也很简单。关键字 this 用于指示特定对象。构造函数中的代码

public Cat(String name, int age) {
    this.name = name;
    this.age = age;
}
几乎可以一字不差地解释:“这只猫的名字(我们正在创建的)= 为构造函数的名称参数传入的参数。这只猫的年龄(我们正在创建的)= 为构造函数的参数传入的参数年龄参数。” 构造函数运行后,您可以验证是否已将所有必要的值分配给我们的猫:

public class Cat {

    String name;
    int age;

    public Cat(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public static void main(String[] args) {

        Cat smudge = new Cat("Smudge", 5);
        System.out.println(smudge.name);
        System.out.println(smudge.age);
    }
}
控制台输出:Smudge 5 调用构造函数时:

Cat smudge = new Cat("Smudge", 5);
这是内部实际发生的事情:

this.name = "Smudge";
this.age = 5;
传递给构造函数的参数值被分配给smudge对象(这就是本例中 this 所指的)。事实上,即使你不在类中声明任何构造函数,它仍然会调用构造函数!但这怎么可能呢?О_О 因为,所有的 Java 类都有一个所谓的默认构造函数。它不接受任何参数,但每次您创建任何类的任何对象时都会调用它。

public class Cat {

    public static void main(String[] args) {

        Cat smudge = new Cat(); // The default constructor is invoked here
    }
}
乍一看,这可能并不明显。我们创建了一个对象,那又如何呢?构造函数在这里做什么?为了看到它,让我们显式地为Cat类编写一个空的构造函数。在其中,我们将向控制台输出一些短语。如果显示该短语,则调用了构造函数。

public class Cat {

    public Cat() {
        System.out.println("A cat has been created!");
    }

    public static void main(String[] args) {

        Cat smudge = new Cat(); // The default constructor is invoked here
    }
}
控制台输出:已创建一只猫!有确认。默认构造函数总是不可见地存在于您的类中。但是你还需要知道一件事。一旦创建带参数的构造函数,默认构造函数就会从类中删除。事实上,我们已经在上面看到了这方面的证据。它在这段代码中:

public class Cat {

    String name;
    int age;

    public Cat(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public static void main(String[] args) {

        Cat smudge = new Cat(); // Error!
    }
}
我们不能创建没有名字和年龄的猫,因为我们声明了一个带有字符串和整数参数的Cat构造函数。这导致默认构造函数立即从类中消失。所以一定要记住,如果你的类中需要多个构造函数,包括一个无参构造函数,你必须单独声明它。我们诊所希望做好事,帮助那些名字和年龄不详的无家可归的小猫。那么我们的代码应该是这样的:

public class Cat {

    String name;
    int age;

    // For cats with owners
    public Cat(String name, int age) {
        this.name = name;
        this.age = age;
    }

    // For street cats
    public Cat() {
    }

    public static void main(String[] args) {
        
        Cat smudge = new Cat("Smudge", 5);
        Cat streetCat = new Cat();
    }
}
现在我们已经指定了一个显式默认构造函数,我们可以创建两种类型的猫。 在构造函数中,可以直接赋值。你不必总是从争论中提取它们。例如,我们可以使用“流浪猫编号 <count>”作为模板来标记数据库中的所有流浪猫。:

public class Cat {

    String name;
    int age;

    static int count = 0;

    public Cat() {
        count++;
        this.name = "Street cat No. " + count;
    }

    public Cat(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public static void main(String[] args) {

        Cat streetCat1 = new Cat();
        Cat streetCat2 = new Cat();
        System.out.println(streetCat1.name);
        System.out.println(streetCat2.name);
    }
}
我们有一个计数变量,它计算我们的流浪猫。每次执行默认构造函数时,我们都会将计数加 1 并将此数字附加到猫的名字上。参数的顺序对于构造函数来说非常重要。让我们交换传递给构造函数的 name 和 age 参数。

public class Cat {

    String name;
    int age;

    public Cat(int age, String name) {
        this.name = name;
        this.age = age;
    }

    public static void main(String[] args) {

        Cat smudge = new Cat("Smudge", 10); // Error!
    }
}
我们得到一个错误!构造函数明确规定,创建Cat对象时,必须依次传递一个数字和一个字符串。所以,我们的代码不起作用。在声明自己的类时一定要记住并遵守这条规则:

public Cat(String name, int age) {
    this.name = name;
    this.age = age;
}

public Cat(int age, String name) {
    this.age = age;
    this.name = name;
}
这是两个完全不同的构造函数!现在,完成几项任务以巩固您对材料的理解。:)
  1. 古物博物馆。

    您的任务是设计一个Artifact类。
    博物馆保存了三种类型的文物。
    除了博物馆分配的序列号(例如:212121)外,我们对第一种一无所知。
    对于第二种类型,我们知道序列号和创建它的文化(例如:212121,“Aztecs”)。
    对于第三种类型,我们知道序列号、创建它的文化以及创建它的世纪(例如:212121,“Aztecs”,12)。

    创建一个Artifact类来描述保存在博物馆中的古物,并为该类编写所需的一组构造函数。然后,在main()方法中,为每种类型创建一个工件。

    
    public class Artifact {
        
        // Write your code here
    
        public static void main(String[] args) {
            // Write your code here
        }
    }
    
  2. 约会网站

    让我们为约会网站创建一个用户数据库。
    但问题是:您忘记了所需的参数顺序,而且没有可用的技术文档。
    设计一个User类,它将具有以下字段:姓名 ( String )、年龄 ( short ) 和身高 ( int )。
    创建适当数量的构造函数,以便可以按任意顺序指定姓名、年龄和身高。

    
    public class User {
    
        String name;
        short age;
        int height;
    
        // Write your code here
    
        public static void main(String[] args) {
            
        }
    }
    
为了巩固您所学的知识,我们建议您观看我们的 Java 课程中的视频课程
评论
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION