4.1 类和对象

类是面向对象的重要内容,可以把类当成一种自定义类型,可以使用类来定义变量,这种类型的变量通称为引用变量。

学习Java的345

三大引用类型:对象、接口、数组

四大修饰符:public|private|protected、final|abstract、static

类的五大主体:成员变量(field)、方法(method)、构造器(constructor)、内部类、初始化模块

一、定义类

类(class)是某一批对象的抽象,可以把类理解成某种概念。

对象(object也称为实例)是类的实例,是一个具体存在的实体。

Java定义类的基本语法如下:

1 [修饰符] class 类名
2 {
3      类的成员变量(field)
4      类的方法定义(Method)
5      类的构造器(constructor)
6      内部类
7      初始化模块  
8  }

修饰符:可以是public、final|abstract,有且仅有,也可以完全省略。

类名:满足标识符的命名规则即可。从专业角度来看,有多个有意义的单词组成,其中每个单词的首字母大写

对于一个类包含5大成员:类的成员变量、方法、构造器、内部类、初始化模块。其中最常见的是成员变量、方法、构造器。如果一个成员也没有,就是一个空类,没有多大的实际意义。

成员变量(由英文单词field意译而来)

  成员变量用于定义该类或该实例所包含的状态数据。定义成员变量的语法格式:

1 [修饰符] 类型 成员变量名[=默认值];

修饰符:修饰符可以省略,也可以是(public|private|protected)、static、final,public|private|protected三个只能出现一个,可以与static、final组合起来修饰成员变量。

类型:包括基本类型和引用类型

成员变量名:只要是一个合法的标识符即可。专业角度采用驼峰写法——首字母小写,后面每个单词首字母大写。

默认值:定义成员变量还可以指定一个可选的默认值。

方法

用于定义该类或该类的实例的行为特征或功能实现

定义方法的语法格式:

1 [修饰符] 方法返回值类型 方法名(形参列表)
2 {
3 //由零条到多条可执行语句组成的方法体
4 }

 修饰符:5大修饰符,public|private|proteced、static、final|abstract,修饰符可以省略

方法返回值类型:返回值的类型可以是Java语言运行的任何数据类型,包括基本类型和引用类型;如果声明了方法返回值类型,则方法体内必须含有一个return语句,该语句返回一个变量或一个表达式,这个变量或表达式的类型必须与此处声明的类型匹配。

方法名:命名规则与成员变量的规则相同

形参列表:形参列表用于定义该方法可以接受的参数,形参列表由零组到多组“参数类型 形参名”组合而成,多参数之间以逗号(,)隔开,形参类型和形参名之间以空格隔开。

注意:static是一个特殊的关键字,它可以修饰成员变量、方法等成员。static修饰的成员表示它属于这个类本身,而不属于类的单个实例,因此通常把static修饰的成员变量和方法称为类变量(静态变量)和类方法(静态方法);不使用static修饰的普通方法、成员变量则属于该类的单个实例,而不属于该类。因此通常把不使用static的成员变量和方法称为实例变量(非静态变量)和实例方法(非静态方法)。

构造器

构造器是创建一个类的根本途径,如果类没有构造器,这个类就无法创建实例。因此,Java语言提供了一个功能:如果程序员没有为一个类编写构造器,则系统会为该类提供一个默认的构造器。一旦程序员为一个类提供了构造器,系统将不再为该类提供构造器。

构造器的语法格式:

1 [修饰符] 构造器名(形参列表)
2 {
3 //由零条或多条可执行语句组成构造器体
4 }

修饰符:可以是public、protected、private之一

构造器名:构造器名必须与类名相同

形参列表:和方法定义形参列表相同。

注意:构造器不能定义返回值类型,也不能使用void声明构造器没有返回值。如果为构造器定义了返回值类型,或使用void声明构造器没有返回值,编译不会出错,但是Java会将这个构造器当成方法处理。

实际上构造器是有返回值的,当使用new关键字来调用构造器时,构造器返回该类的实例,可以把这个实例当成构造器的返回值类型,因此构造器的返回值类型总是当前类,无需定义返回值类型。但注意不要在构造器里显示使用return来返回当前类的对象,因为构造器的返回值是隐式的。

定义一个类:

 1 class Person
 2 {
 3 //定义成员变量
 4 public int age;
 5 public String name;
 6 //age=20;这不是一个类,这是一个赋值语句,不属于类的五大成员
 7 //定义一个say方法
 8 public void say(String content)
 9     {
10         System.out.println(content);
11     }
12 }

 二、类的产生和引用以及引用与指针

创建对象的根本途径就是构造器,通过new关键字来调用某个类的构造器可创建这个类的实例。(如果没有定义构造器、系统会为该类提供一个默认的构造器)。

类是一类对象的抽象,对象是类的实体。

类的可以做什么:

(1)定义变量:所有类都是引用类型,都可以用于声明变量。

(2)调用类变量和类方法(static修饰的变量和static修饰的方法)。

(2)创建对象。new 构造器 (参数列表)——构造器名必须与类名一致

对象可以做什么?

(1)调用对象的实例变量(无static修饰的变量)

(2)调用对象的方法(无static修饰的方法)

如果访问权限允许,类里定义的变量和方法都可以通过类或实例来调用。static修饰的成员变量和方法,既可以通过类来调用,也可以通过实例来调用;没有static修饰的普通方法和成员变量,只能通过实例来调用。

类的成员变量或方法调用语句:

类.类变量|类方法

 实例:定义一个Person类

 1 public class  Person
 2 {
 3     //定义成员变量
 4     public String name;
 5     public int age;
 6     static int MAXNUM=20;//这是一个类变量
 7 
 8     //这是一个类方法
 9     static public void walk()
10     {
11         System.out.println("没病走两步");
12     }
13 
14     //下面定义一个say方法
15     public void say(String content)
16     {
17         System.out.println(content);
18     }
19 }

 通过new关键字来调用Person类的构造器,来返回该类的实例。

 1 class Classuse 
 2 {
 3     public static void main(String[] args) 
 4     {
 5         //定义一个Person类型的变量
 6         //Person p;
 7         //通过new关键字调用Person类的构造器,返回一个Person实例
 8         //p=new Person();
 9         //上面两行代码也可以用一行代替
10         var p=new Person();
11 
12         //调用类方法可以用对象去调用,也可以使用类调用
13         System.out.println(Person.MAXNUM);
14         System.out.println(p.MAXNUM);
15 
16         //普通成员变量只能通过对象来调用
17         p.say("这是一个普通方法(对象的方法)");
18         
19         /*
20          *Person.say("通过类调用");
21          *Classuse.java:18: 错误: 无法从静态上下文中引用非静态 方法 say(String)
22          */
23         
24         Person.walk();
25         p.walk();
26     }  
27 }

 首先var p=new Person();实际上产生了两个东西,一个是p变量,一个是Person对象

类也是一种引用数据类型,因此定义Person类型的变量实际上是一个引用,它被放在栈(stack)内存中,指向实际的Person对象;而真正的Person对象则放在堆内存(heap)中。栈内存里的引用变量并未真正存储对象的成员变量,对象的成员变量实际存储在堆内存中;而引用变量的只是指向该堆内存里的对象。实际上Java的引用就是C语言的指针,只是Java把这个指针封装起来,避免了开发者进行繁琐的指针操作。

Java程序不允许直接访问堆内存中的对象,只能过该对象的引用来操作该对象。

堆内存中的对象可以由,多个引用,即多个引用指向同一个对象,代码如下:

var p1=p;

 如果堆内存中的对象没有任何引用指向该对象,那么程序无法访问该对象,该对象也就变成垃圾,Java的垃圾回收器将回收该对象,释放该对象所占的内存区。因此希望通知垃圾回收器回收某个对象,可以将该对象的引用变量赋值为null。

三、对象this引用

this关键字总是指向调用该方法的对象。根据this出现的位置不同,this作为对象的默认引用有两种情形。

1、在非static修饰的方法中,this代表方法的调用者。

this关键字最大的作用是让类中的一个方法,访问该类里的另一个方法或实例变量。

 1 class Dog
 2 {
 3     public String color;
 4     public void bark()
 5     {
 6         System.out.println("汪!汪!汪!");
 7     }
 8 
 9     //定义一个run方法,在run()方法中需要调用bark()方法
10     public void run()
11     {
12         System.out.println("小狗狗正在跑~");
13         this.bark();
14     }
15 }

在DogTest.java中调用Dog类中的方法。

 1 class DogTest 
 2 {
 3     public static void main(String[] args) 
 4     {
 5         //创建dog对象
 6         Dog d=new Dog();
 7         //调用run()方法,此时run()方法的this代表Dog对象d
 8         d.run();
 9     }
10 }
11 ---------- 运行Java捕获输出窗 ----------
12 小狗狗正在跑~
13 汪!汪!汪!
14 
15 输出完成 (耗时 0 秒) - 正常终止

this可以代表任何对象,当this出现在某个方法体中,它所代表的对象是不确定的,但它的类型是确定的;它所代表的只能是当前类的实例;只有当该方法调用时,它所代表的对象才被确定下来。谁在调用这个方法,this就代表谁。

这种用法符合实际情形:当一个Dog对象调用run()方法时,run()方法需要依赖它自己的bark()方法。通常Java一个成员调用另外一个成员时,this可以省略。上面的this.bark();可以用bark();代替。

注意:对于static修饰的方法而言,则可以使用类来直接调用该方法,如果在static修饰的方法中使用this关键字,则这个关键字无法指向合适的对象。所以说,static修饰的方法中不能使用this引用。由于static修饰的方法不能使用this引用,所以static修饰的方法不能访问不使用static修饰的普通成员,因此Java规定:静态成员不能直接访问非静态成员。一般来说,如果调用static修饰的成员时省略了前面的主调,那么默认使用该类作为主调;如果调用没有static修饰的成员时省略了前面的主调,那么默认使用this作为主调。

下面演示静态方法直接访问非静态方法时引发的错误。

class StaticToNonstatic 
{
    //定义一个普通类
    public void info()
    {
        System.out.println("测试info方法");
    }

    //main方法是一个静态方法
    public static void main(String[] args) 
    {
        //调用main方法的是StaticToNonstatic类,而不是该类的实例
        //而info方法是一个非静态方法,只能通过实例调用
        //this.info();或
        info();
    }
}
---------- 编译Java ----------
StaticToNonstatic.java:15: 错误: 无法从静态上下文中引用非静态 方法 info()
        info();
        ^
1 个错误

输出完成 (耗时 1 秒) - 正常终止

大部分时候,普通方法访问其他方法、成员变量时无需使用this前缀,但如果方法中有个局部变量与成员变量同名,但程序又需要访问这个被覆盖了的局部变量,则必须使用this前缀。

2、出现在构造器中引用正在初始化的对象。

this引用也可以用与构造器中作为默认引用,由于构造器中直接使用new关键字来调用,而不是使用对象来调用的,所以this在构造器中代表该构造器正在初始化的对象。

大部分时候,在构造器中访问其他方法、成员变量时无需使用this前缀,但如果构造器中有个局部变量与成员变量同名,但程序又需要访问这个局部变量,则必须使用this前缀。

 1     public int foo;
 2 
 3     //构造器必须与类名相同
 4     public ThisConstructor()
 5         {
 6             //在构造器中定义一个局部变量foo
 7             int foo=1;
 8             //在构造器中对成员变量初始化为10
 9             this.foo=10;
10         }
11 
12     public static void main(String[] args) 
13     {
14         var p=new ThisConstructor();
15         //此时构造器中的this代表对象p
16         System.out.println(p.foo);
17     }
18 }
19 ---------- 运行Java捕获输出窗 ----------
20 10
21 
22 输出完成 (耗时 0 秒) - 正常终止

猜你喜欢

转载自www.cnblogs.com/weststar/p/12334969.html