zoukankan      html  css  js  c++  java
  • 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 秒) - 正常终止
  • 相关阅读:
    Redis持久化
    Redis数据淘汰策略
    Redis事务
    Redis发布订阅
    WPS生成多级编号
    VMware 网络介绍
    3、Linux目录操作
    2、Shell命令学习笔记
    2、线程的状态和调度学习笔记
    1、Linux安装前的准备
  • 原文地址:https://www.cnblogs.com/weststar/p/12334969.html
Copyright © 2011-2022 走看看