Java 的对象与类(一)

Java 的对象与类(一),第1张

Java 的对象与类(一)
    • 对象和类
    • 1. 成员变量和成员方法
    • 2. 由类构造对象的过程称为创建类的实例
    • 3. 访问类中成员变量
      • (1)展示1
      • (2)展示2
    • 4. 访问类中的成员方法
    • 5. 静态的成员
    • 6. 静态与非静态的关系
    • 7. 说明两种情况
    • 8. 介绍 toString 方法
    • 9. 构造方法
    • 10. 代码块
    • 11. 匿名对象

对象和类 1. 成员变量和成员方法

在程序清单1中,我们创建一个类 Person
name,age 被称为 字段/属性/成员变量(类的内部,方法的外部)
eat(),sleep() 被称为成员方法,表示类中的某种行为

程序清单1:

class Person{
    public String name;
    public int age;
    public void eat(){
        System.out.println(name+" 正在吃饭");
    }
    public void sleep(){
        System.out.println(name+" 正在睡觉");
    }
}

public class Test {
    public static void main(String[] args) {
        Person person = new Person();
    }
}

2. 由类构造对象的过程称为创建类的实例

也就是说:对象是通过类实例化出来的
new Person( ) 这个表达式构造了一个新的对象,person 就是被类 Person 创建的一个对象变量。
Person 在 Java 中表示的是引用类型,它在意义上相当于 int,因为 int 是整型。
person 是通过引用类型定义的,所以 person 就是引用变量,也可以把 person 叫做对象的引用。

Person person = new Person();
int a = 10;

类 Person 相当于一个模板,它可以实例化多个对象

public class Test {
    public static void main(String[] args) {
        Person person1 = new Person();
        Person person2 = new Person();
        Person person3 = new Person();
        Person person4 = new Person();
        Person person5 = new Person();
    }
}

3. 访问类中成员变量

访问类中成员变量的格式:[ 对象变量 ] + . + [ 字段 ]
如:person.name

(1)展示1

程序清单2:

class Person{
    public String name;
    public int age;
    boolean result;
}

public class Test {
    public static void main(String[] args) {
        Person person = new Person();
        System.out.println(person.name);
        System.out.println(person.age);
        System.out.println(person.result);
    }
}

输出结果:

在程序清单2中,字段/成员变量 如果未被初始化,那么 int 类型默认为0,String 类型默认为null,boolean 类型默认为 false.

(2)展示2

程序清单3:

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

public class Test {
    public static void main(String[] args) {
        Person person1 = new Person();
        Person person2 = new Person();
        Person person3 = new Person();
        person2.name = "吉姆";
        person2.age = 17;
        person3.name = "露丝";
        person3.age = 21;

        System.out.println(person1.name);
        System.out.println(person1.age);
        System.out.println("-----------------");
        System.out.println(person2.name);
        System.out.println(person2.age);
        System.out.println("-----------------");
        System.out.println(person3.name);
        System.out.println(person3.age);
    }
}

输出结果:我们可以看到,创建一个对象,那么赋值给类的时候,这些值就属于对象了。

在程序清单3中,类是对象的模板。

接下来我举个例子:刚开始,我没有创建对象的时候,这块模板是崭新的,什么颜色也没有。而当我新创建了一个对象的时候,我就拿到了这个崭新的模板,此时我可以给这个模板上色,让它变成蓝色。然而,我又可以创建另一个对象,此时我又拿到了一块崭新的模板,我可以给这个模板上色,让它变成绿色…当我不给这块模板上色的时候,它依然是那块崭新的模板。没错,就是这么回事儿!

简而言之,只要我通过类 Person 创建了一个对象,那么我就拿到了一个初始类中的所有字段,我就可以对这个类进行改造,而 person1,person2,person3 两两类之间没有任何关联。

4. 访问类中的成员方法

访问类中的方法的格式: [ 对象变量 ] + . + [ 方法 ]
如: person1.eat( )

程序清单4:

class Person{
    public String name;
    public void eat(){
        System.out.println(name+" 正在吃饭");
    }
    public void sleep(){
        System.out.println(name+" 正在睡觉");
    }
}

public class Test {
    public static void main(String[] args) {
        Person person1 = new Person();
        person1.name = "吉姆";
        person1.eat();
        
        Person person2 = new Person();
        person2.name = "露丝";
        person2.sleep();
    }
}

5. 静态的成员

静态成员被 static 关键字修饰,在介绍静态成员之前,读者请看一个例子

程序清单5:

class Person{
    public int count;
    public static int size;
}

public class Test {
    public static void main(String[] args) {
        Person person1 = new Person();
        Person person2 = new Person();

        person1.count++; //1
        System.out.println(person1.count);
        person2.count++; //1
        System.out.println(person2.count);
        System.out.println("---------------");

        person1.size++; //1
        System.out.println(person1.size);
        person2.size++; //2
        System.out.println(person2.size);
    }
}

输出结果

我相信通过上面的介绍,对于 person1.count++ 和 person2.count++,大家已经不陌生了,因为 count 是通过对象变量进行 *** 作的,person1 和 person2 是两个不同的对象变量,也就是两个不同对象 *** 作的结果,所以各自为1,互不影响。

而通过关键字 static 修饰的 size 就不同了,因为 static 修饰的成员变量被放置在方法区,只有一份,所以 person1.size++ 和 person2.size++ 其实是对同一份的 size 进行 *** 作。

那么我们就可以通过类直接访问静态成员变量了!
访问格式:[ 类名 ] . [ 静态成员变量 ]

程序清单6:

class Person{
    public static int size;
}

public class Test {
    public static void main(String[] args) {
        Person.size++; //1
        System.out.println(Person.size);
        Person.size++; //2
        System.out.println(Person.size);
    }
}

程序清单7:

class Person{
    public static String name1;
    public static void run(){
        System.out.println(name1 + " 正在跑步");
    }
}
public class Test {
    public static void main(String[] args) {
        Person.name1 = "杰克";
        Person.run();
    }
}

输出结果:

结论:
① 被 static 关键字修饰的变量和方法由类直接控制,被所有类共享。
② 被 static 关键字修饰的变量不属于对象,或者说不依赖于对象,所以它也被叫做类变量。
③ 被 static 关键字修饰的方法不属于对象,或者说不依赖于对象,所以它也被叫做类方法。

6. 静态与非静态的关系

在程序清单8中,其中有两行代码会被编译器报错,我已经通过注释标明出来了。
我想说明的问题是,不论在静态成员方法中,还是在非静态成员方法中,我们都无法定义静态的变量,因为我们要时刻记住,关键字 static 修饰的变量永远是属于类的,不属于某个方法,我们只能通过类来访问和 *** 作!

程序清单8:

class Person{
    public static String name1;
    public void swim(){
        static int a = 10; //error
        System.out.println(name1 + " 正在游泳");
    }
    public static void run(){
        static int b = 10; //error
        System.out.println(name1 + " 正在跑步");
    }
}

同样地,关于静态的方法也有讲究,非静态的方法可以调用静态的方法,而静态的方法不能调用非静态的方法 ,因为静态的方法不依赖对象,非静态的方法依赖对象。

程序清单9:

class Person{
    public static String name1;
    public void swim(){
        run();
        System.out.println(name1 + " 正在游泳");
    }
    public void eat(){
        swim();
        System.out.println(name1 + " 正在吃饭");
    }
    
    public static void run(){
        swim(); //error
        System.out.println(name1 + " 正在跑步");
    }
    public static void sleep(){
        run(); 
        System.out.println(name1 + " 正在睡觉");
    }
}

拓展一下,如果有的人性格就比较犟,就要用静态的方法调用非静态的方法,那么我们就在调用之前,在静态的方法中创建一个对象就行了,举个例子:通过对象变量 person 访问 swim( ) 即可,但是很少有人这么做,因为无非就是加或不加 static 的事情,我只是想更深刻地理解这些知识,所以展示的代码如下:

程序清单10:

class Person{
    public static String name1;
    public void swim(){
        run();
        System.out.println(name1 + " 正在游泳");
    }    
    public static void run(){
        Person person = new Person();
        person.swim(); //right
        System.out.println(name1 + " 正在跑步");
    }
}

7. 说明两种情况

① person 这个引用不指向任何的对象

Person person = null;

② person2 这个引用指向 person1 这个引用指向的对象

Person person1 = new Person();
Person person2 = person1;

程序清单11:

class Person{
    public int age;
}

public class Test {
    public static void main(String[] args) {
        Person person = null;
        Person person1 = new Person();
        Person person2 = person1;
        person1.age = 10;
        System.out.println(person2.age); //输出10     
    }
}

8. 介绍 toString 方法

① 程序清单12:

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

public class Test {
    public static void main(String[] args) {
        Person person = new Person();
        person.name = "吉姆";
        person.age = 18;
        System.out.println(person);
    }
}

程序清单12的输出结果:demo3 表示一个包,Person 表示包下的一个类,@… 表示地址
我们打印的是对象变量 person,即表示引用变量指向的地址。

程序清单13:

class Person{
    public String name;
    public int age;

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

public class Test {
    public static void main(String[] args) {
        Person person = new Person();
        person.name = "吉姆";
        person.age = 18;
        System.out.println(person);
    }
}


在程序清单13中,我们使用了 toString 方法:

@Override 表示重写,public String toString( ) 这个方法是通过 IDEA 编译器自动生成的,它可以返回表示对象值的字符串,这样做的目的是:程序员清楚地知道对象的状态,同时也提升了其他人的代码可读性。

9. 构造方法

对创建构造方法进行一些说明:
(1)构造方法的方法名和类名是相同的
(2)构造方法比较特殊,没有返回值
(3)构造方法之间构成重载

那么如何使用创建的构造方法呢?在通过关键字 new 创建对象的时候,我们就可以输入构造方法中对应的参数了。详见程序清单14.

程序清单14:

class Person{
    public String name;
    public int age;
    public Person(){
        System.out.println("调用不带参数的构造方法");
    }
    public Person(String name){
        this.name = name;
        System.out.println("调用带有一个参数的构造方法");
    }
    public Person(String name,int age){
        this.name = name;
        this.age = age;
        System.out.println("调用带有两个参数的构造方法");
    }
}

public class Test {
    public static void main(String[] args) {
        Person person1 = new Person();
        Person person2 = new Person("罗恩");
        Person person3 = new Person("杰克",21);
    }
}

在程序清单15中,在类 Test 中, 如果你没有实现任何的构造方法时,编译器会帮我们默认生成一个不带参数的构造方法,也就是说,一个类至少有一个构造方法,即使你没有写!

程序清单15:

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

public class Test {
    public static void main(String[] args) {
        Person person1 = new Person();
    }
}

编译器自动生成的构造方法就是如下代码:

public Person(){

}
10. 代码块

(1)实例代码块

{

}

(2)静态代码块

static
{

}

让我们来看看以下的几个程序清单:

程序清单16:

class Student{
    public String name;
    public int age;
    public static double grade;
    {
        name = "李明";
        age = 17;
    }
    static
    {
        grade = 88.5;
    }
}

public class Test {
    public static void main(String[] args) {
        Student student1 = new Student();
        System.out.println(student1.name);
        System.out.println(student1.age);
        System.out.println(Student.grade);
    }
}

输出结果:

程序清单17:

class Student{
    public Student(){
        System.out.println("不带参数的代码块");
    }

    {
        System.out.println("实例代码块");
    }

    static
    {
        System.out.println("静态代码块");
    }
}

public class Test {
    public static void main(String[] args) {
        Student student1 = new Student();
        System.out.println("----------------");
        Student student2 = new Student();
    }
}

输出结果:

程序清单18:

class Student{
    public static int count;
    public Student(){
        System.out.println("不带参数的代码块");
    }

    {
        System.out.println("实例代码块");
    }
    static
    {
        count++;
        System.out.println("静态代码块");
    }
}
public class Test {
    public static void main(String[] args) {
        System.out.println(Student.count);
    }
}

输出结果:

程序清单19:

class Person{
    public static int count;
    static
    {
        count = 10;
    }
}

public class Test {
    public static void main(String[] args) {
        System.out.println(Person.count); //10
    }
}

程序清单20:

class Person{
    static
    {
        count = 10;
    }
    public static int count;
}

public class Test {
    public static void main(String[] args) {
        System.out.println(Person.count); //10
    }
}

程序清单21:

class Person{
    static
    {
        count = 10;
    }
    public static int count = 99;
}

public class Test {
    public static void main(String[] args) {
        System.out.println(Person.count); //99
    }
}

总结:

① 实例代码块被用来初始化非静态成员变量的值,静态代码块被用来初始化静态成员变量的值。
② 静态代码块执行完毕后, 实例代码块(构造块)执行,再然后是构造函数执行。
③ 静态代码块不管生成多少个对象,其只会执行一次,且是最先执行的。
④ 静态代码块中的成员变量被赋值,最终输出的结果和顺序有关。

11. 匿名对象

让我们来看看程序清单22,我们就能明白匿名对象的含义了。
匿名对象表示没有引用的对象,new Person( ) 只能被用一次,而且在下一次这么用的时候,不会衔接上一个变量值,这就相当于,一个对象只被用了一次,之后就恢复到原始状态了。

程序清单22:

class Person{
    public String name;
    public void swim(){
        System.out.println(name + " 正在游泳");
    }
    public  void run(){
        System.out.println(name + " 正在跑步");
    }
}

public class Test {
    public static void main(String[] args) {
        new Person().name = "Jack";
        System.out.println(new Person().name);
        new Person().swim();
        new Person().run();
    }
}

欢迎分享,转载请注明来源:内存溢出

原文地址: https://www.outofmemory.cn/langs/891921.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-14
下一篇 2022-05-14

发表评论

登录后才能评论

评论列表(0条)

保存