03 【类、对象和方法】以及【方法的重载与重写的区别】

1、类class

  • 类可以理解为一个模板,由此模板可以创建很多具备某些共同特征的实体,它是一种抽象的数据类型,它是对所具有相同特征实体的抽象。在面向对象的程序设计语言中,类是对一类“事物”的属性与行为的抽象。
  • 在定义类时,每个类首字母要大写,且类名必须与文件名相同。当一个文件含有多个类时,文件名与主类一致。(每个文件至多有一个主类)。
  • 同类的多个对象常常具有一些共性。比如:所有的学生都有学号、姓名、性别、出生日期等。将同类对象的共性抽象出来,就形成了类(class)。
  • 用类创建一个对象的过程就叫实例化。对象也可以叫实例。我创建一个学生的类,就可以创建一个学生对象。
  • 类是创建对象的模板,它定义了对象应该具有哪些数据(变量)以及操作这些数据的代码(方法)。
    类=属性(变量)+行为(方法)
  • 类的定义:
      [修饰符] class 类名{
       0–n个成员变量(属性) //语法格式:[修饰符] 数据类型 成员变量名 [=值]
       0—n个方法(行为)
    }

一个类可以包含以下类型变量:

  • 局部变量:在方法、构造方法或者语句块中定义的变量被称为局部变量。变量声明和初始化都是在方法中,方法结束后,变量就会自动销毁。
  • 成员变量:成员变量是定义在类中,方法体之外的变量。这种变量在创建对象的时候实例化。成员变量可以被类中方法、构造方法和特定类的语句块访问。
  • 类变量:类变量也声明在类中,方法体之外,但必须声明为 static 类型。
    一个类可以拥有多个方法:barking()、hungry() 和 sleeping() 都是 Dog 类的方法

  • 类有抽象类,没有静态类(但有静态内部类,如果一个类要被声明为static的,只有一种情况,就是静态内部类。)

关于抽象类

  • 抽象类除了不能实例化对象之外,类的其它功能依然存在,成员变量、成员方法和构造方法的访问方式和普通类一样。
      由于抽象类不能实例化对象,所以抽象类必须被继承,才能被使用。也是因为这个原因,通常在设计阶段决定要不要设计抽象类。
      父类包含了子类集合的常见的方法,但是由于父类本身是抽象的,所以不能使用这些方法。
      在Java中抽象类表示的是一种继承关系,一个类只能继承一个抽象类,而一个类却可以实现多个接口。

  • 如果你想设计这样一个类,该类包含一个特别的成员方法,该方法的具体实现由它的子类确定,那么你可以在父类中声明该方法为抽象方法。
      Abstract 关键字同样可以用来声明抽象方法,抽象方法只包含一个方法名,而没有方法体。
      抽象方法没有定义,方法名后面直接跟一个分号,而不是花括号。

  1. 抽象类不能被实例化(初学者很容易犯的错),如果被实例化,就会报错,编译无法通过。只有抽象类的非抽象子类可以创建对象。

  2. 抽象类中不一定包含抽象方法,但是有抽象方法的类必定是抽象类。

  3. 抽象类中的抽象方法只是声明,不包含方法体,就是不给出方法的具体实现也就是方法的具体功能。

  4. 构造方法,类方法(用 static 修饰的方法)不能声明为抽象方法。

  5. 抽象类的子类必须给出抽象类中的抽象方法的具体实现,除非该子类也是抽象类。如果一个类包含抽象方法,那么该类必须是抽象类。
    任何子类必须重写父类的抽象方法,或者声明自身为抽象类。
    继承抽象方法的子类必须重写该方法。否则,该子类也必须声明为抽象类。最终,必须有子类实现该抽象方法,否则,从最初的父类到最终的子类都不能用来实例化对象。
                                                                       
    格式: {修饰符} abstract 返回类型 方法名();
    修饰符(pubic protected private)三选一


定义了一个类之后,就可以利用这个类创建对象了,比如我创建了Student类,就可以创建一个对象了:
Student st1 = new Student();
Student st2 = new Student();

//变量st1为Student类型,就像int b;变量b为int类型一样理解
这条语句意思为:把创建的Student类型的对象的引用存放到Student类型的变量st1中保存

=============================================================================================================================================

2、对象

2.1简介

  • 对象是类的一个实例,有状态和行为。java程序是由许多对象组成,每个对象有自己的属性(变量)和行为(方法)。例如,一条狗是一个对象,它的状态有:颜色、名字、品种;行为有:摇尾巴、叫、吃等。
  • 对象之间通过方法调用来完成任务
  • 一个对象不能直接访问另一个对象内部的数据,反之一样
  • 在Java中,使用关键字 new 来创建一个新的对象。创建对象需要以下三步:
    声明:声明一个对象,包括对象名称和对象类型。
    实例化:使用关键字 new 来创建一个对象。【类实例化(赋予给定值)】
    初始化:使用 new 创建对象时,会调用构造方法初始化对象。【类构造器完成类初始化(分配内存、赋予默认值)】

2.2创建对象的几种方式

其实对象的初始化就是在创建对象的时候由jvm完成的。对于创建对象,主要是研究创建对象的几种方式。下面一一的解答.这里给出6种方式,(可以看出创建一个对象不仅仅只局限于new关键字)

1.使用new关键字
2.Class对象的newInstance()方法
3.构造函数对象的newInstance()方法
4.对象反序列化
5.Object对象的clone()方法
6.使用Unsafe类创建对象


2.3 为什么要创建对象

  • 没有使用static修饰的成员变量和方法都需要使用对象来调用
      当一个对象被创建成功后,这个对象将保存在堆内存中,java程序不允许直接访问堆内存中的对象,只能通过该对象的引用操作该对象(如Person p = newPerson(),,,p.setName(),这里的p就是那个对象的引用)
    【要使用类中的方法(除了静态方法),就必须要实例化(申请空间等),才能使用。】
    【我们写代码时,都是在每个java文件里写class,class里有属性和方法。然后在main方法里new对象来调用方法,变量等。】
    =========================================================================================================================================================================================

3、方法

  • 方法必须定义在某个类中,定义格式:
     [权限修饰符]  返回值类型  方法名(0-n个“参数类型  参数名”){
       方法体;
      }
     成员变量和成员方法没有顺序要求,在成员方法中可直接访问成员变量
     //如果声明了不为void的返回值类型,则方法体内必须有一条return语句。该语句返回一个与声明的方法返回值类型相同的变量或表达式。
     //不需要返回值时方法返回值类型用void
  •   需要什么功能就去创建什么方法。然后去调用这个方法。方法的调用需要借助对象.方法名

3.1 方法的调用

除了main方法外,其他方法若需要执行就需要调用该方法,程序的执行时在main方法里由上往下执行的。调用方法在main方法里调用。
类名.方法名(实际参数1、2、······)

  • 对于形参列表,有0—n组“参数类型 参数名“组合而成。一旦在定义该方法时指定了参数列表,则调用该方法时必须传入对应的参数值(谁调用方法,谁就为形参赋值),赋完值执行完该方法后,有返回值时返回给调用处。形参列表中的每一个参数都是局部变量,方法结束后内存释放
  • 调用某方法时要学会带着实际参数到这个方法的位置那里,然后把参数对应传入。当定义的这个方法有返回值时,调用处可以方法返回值,如a.getNum(3,2);这里是调用处,则带着实际参数执行完方法后得到的值会返回给a.getNum(3,2),如果用c去接收int c = a.getNum(3,2)。C就等于这个返回值。
  • Main方法里只给实际参数,想要有什么功能就在具体方法里实现体现
  • 如何知道要使用方法呢?
    当你要实现一个功能并且需要重复利用该功能时就需要构建方法。

  • 由类生成对象的过程称为创建类的实例(instance),因此,对象也称为类的实例(instance)。

  • 类中的变量和方法称为类的成员(member)。成员变量也叫实例变量。成员方法也叫实例方法


3.2 局部变量

方法作用域中定义的变量称为局部变量。(类体中方法外定义的变量为全局变量,全局变量也成为成员变量)
   作用域的基本原则:在当前作用域中声明的变量,对于该作用域之外的代码是不可见的。
   在外层作用域中声明的变量,在内层作用域中可以使用,反之则不行。
   当离开变量的作用域,该变量即被释放。
   变量按作用域分为:局部变量(定义在方法内部)、全局变量(定义在方法外类内、成员变量)
   所有在方法中声明的变量,都放在对应的栈内。

1)作用域
​ 成员变量:针对整个类有效。
​ 局部变量:只在某个范围内有效。(一般指的就是方法,语句体内)
​ (2)存储位置
成员变量:随着对象的创建而存在,随着对象的消失而消失,存储在堆内存中。

3.2 方法的种类

1. 静态方法

静态方法只能访问静态成员,实例方法可以访问静态和实例成员。之所以不允许静态方法访问实例成员变量,是因为实例成员变量是属于某个对象的,而静态方法在执行时,并不一定存在对象。静态方法中也不能使用关键字this。

  • 静态方法的访问:不需要new对象,直接用该静态方法所在类的类名.静态方法名就行。
  • (1)static修饰的静态方法会随着类的定义而被分配和装载入内存中,编译器只为整个类创建了一个静态变量的副本,也就是只分配一个内存空间,虽然可能有多个实例,但这些实例共享该内存,特别值得注意的是,任何一个对象对静态数据成员的修改,都会影响其它对象。
    (2)静态不能引用非静态这一特性,是由于静态的会随着类的定义而被分配和装载入内存中这一关键点决定的;如果静态引用了非静态的,根本无法从内存中找到非静态的代码段,势必会出错,这种做法是Java虚拟机决不允许的。
import java.util.*;//代码转载他人

public class TestStatic {
    public static void main(String[]args){
        System.out.println(S.getStatic());//使用类名加前缀访问静态方法
        S s=new S();
        System.out.println(s.getStatic());//使用实例化对象名访问静态方法
        System.out.println(s.get());
    }
    public static class S
    {
        private static int a;
        private int t=0;

        //静态初始器:由static和{}组成,只在类装载的时候(第一次使用类的时候)执行一次,往往用来初始化静态变量。
        static{
            a=10;
        }

        //静态方法只能访问静态数据成员
        public static int getStatic()
        {
            return a;
        }

        public int getT()
        {
            return t;
        }

        //非静态方法可以访问静态方法和非静态方法
        public int get()
        {
            getT();
            getStatic();
            t=a;//非静态方法可以访问非静态数据成员和静态数据成员
            return t;
        }
    }
}
2. 成员方法

成员方法描述对象所具有的功能或操作,反映对象的行为,是具有某种相对独立功能的程序模块。
一个类或对象可以有多个成员方法,对象通过执行它的成员方法对传来的消息作出响应,完成特定的功能。成员方法一旦定义,便可在不同的程序段中多次调用,故可增强程序结构的清晰度,提高编程效率。

1 成员方法的分类
   从成员方法的来源看,可将成员方法分为: 类库成员方法。这是由 Java 类库提供的,用户只要按照 Java 提供的调用格式去使用这些成员方法即可。用户自定义的成员方法。这是为了解决用户的特定问题,由用户自己编写的成员方法。程序设计的主要工作就是编写用户自定义类、自定义成员方法。 从成员方法的形式看,可将成员方法分为: 无参数成员方法。带参数成员方法。
   
2 声明成员方法的格式
  在 Java 程序中,成员方法的声明只能在类中进行,
  
3 方法体中的局部变量
  在方法体内可以定义本方法所使用的变量,这种变量是局部变量,它的生存期与作用域是在本方法内。也就是说,局部变量只能在本方法内有效或可见,离开本方法则这些变量被自动释放。 方法体内定义变量时,变量前不能加修饰符。局部变量在使用前必须明确赋值,否则编译时会出错。在一个方法内部,可以在复合语句中定义变量,这些变量只在复合语句中有效,这种复合语句也被称为程序块。
  
4 成员方法的返回值
  若方法有返回值,则在方法体中用 return 语句指明要返回的值。 其格式为:return 表达式;或return(表达式);表达式可以是常量、变量、对象等。 return 语句后面表达式的数据类型必须与成员方法头中给出的“返回值的类型”一致。
  
5 形式参数与实际参数
  一般来说,可以通过以下方式来引用成员方法:成员方法名(实参列表)在引用成员方法时应注意: 对于无参成员方法来说,是没有实际参数列表的,但方法名后的括弧不能省略。对于带参数的成员方法来说,实参的个数、顺序以及它们的数据类型必须与形式参数的个数、顺序以及它们的数据类型保持一致,各个实参间用逗号分隔。实参名与形参名可以相同也可以不同。实参也可以是表达式,此时一定要注意使表达式的数据类型与形参的数据类型相同,或者使表达式的类型按 Java 类型转换规则达到形参指明的数据类型。实参变量对形参变量的数据传递是“值传递”,即只能由实参传递给形参,而不能由形参传递给实参。程序中执行到引用成员方法时,Java 把实参值拷贝到一个临时的存储区(栈)中,形参的任何修改都在栈中进行,当退出该成员方法时,Java 自动清除栈中的内容。
  
6 成员方法的引用方式
  6.1 方法语句
    成员方法作为一个独立的语句被引用。
  6.2 方法表达式
     成员方法作为表达式中的一部分,通过表达式被引用。
   6.3 方法作为参数
      一个成员方法作为另一个成员方法的参数被引用。更为典型的是,在递归的成员方法中,一个成员方法作为它自身的参数被引用。6.4 通过对象来引用 这里有两重含义,一是通过形如“对象名.方法名”的形式来引用对象,二是当一个对象作为成员方法的参数时,通过这个对象参数来引用对象的成员方法。
     
7 引用成员方法时应注意的事项
  当一个方法引用另一个方法时,这个被引用的方法必须是已经存在的方法。另外,还要视被引用的成员方法存在于何处而做不同的处理。 如果被引用的方法存在于本文件中,而且是本类的方法,则可直接引用。如果被引用的方法存在于本文件中,但不是本类的方法,则要考虑类的修饰符与方法的修饰符来决定是否能引用。如果被引用的方法不是本文件的方法而是 Java 类库的方法,则必须在文件的开头处用 import 命令将引用有关库方法所需要的信息写入本文件中。如果被引用的方法是用户在其他的文件中自己定义的方法,则必须通过加载用户包的方式来引用。
  
8 成员方法的递归引用
  成员方法的递归引用就是指在一个方法中直接或间接引用自身的情况。
  
9 static 修饰的静态方法
  用 static 修饰符修饰的方法被称为静态方法,它是属于整个类的类方法。不用 static 修饰符限定的方法,是属于某个具体类对象的方法。 static 方法使用特点如下: static 方法是属于整个类的,它在内存中的代码段将随着类的定义而分配和装载。而非 static 的方法是属于某个对象的方法,当这个对象被创建时,在对象内存中拥有这个方法的专用代码段。引用静态方法时,可以使用对象名做前缀,也可以使用类名做前缀。static 方法只能访问 static 数据成员,不能访问非 static 数据成员,但非 static 方法可以访问 static 数据成员。static 方法只能访问 static 方法,不能访问非 static 方法,但非 static 方法可以访问 static 方法。main 方法是静态方法。在 Java 的每个 Application 程序中,都必须有且只有一个 main 方法,它是 Application 程序运行的入口点。
  
10数学函数类方法
  Java 类库提供的实现常用数学函数运算的标准数学函数方法,这些方法都是 static 方法。 标准数学函数方法在 Java.lang.Math 类中,使用方法比较简单,格式如下:类名.数学函数方法名(实参列表)
  
11 final 修饰的最终方法
  用 final 修饰符修饰的方法称为最终方法,如果某个方法被 final 修饰符所限定,则该类的子类就不能覆盖父类的方法,即不能再重新定义与此方法同名的自己的方法,而仅能使用从父类继承来的方法。使用 final 修饰方法,就是为了给方法“上锁”,防止任何继承类修改此方法,保证了程序的安全性和正确性。 注意:final 修饰符也可用于修饰类,而当用 final 修饰符修饰类时,所有包含在 final 类中的方法,都自动成为 final 方法。
  
12 native 修饰的本地方法
  修饰符 native 修饰的方法称为本地方法,此方法使用的目的是为了将其他语言(如 C、C++、Fortran、汇编等)嵌入到 Java 语言中。这样,Java 可以充分利用已经存在的其他语言的程序功能模块,避免重复编程。 在 Java 程序中使用 native 方法时应该特别注意平台问题。由于 native 方法嵌入其他语言书写的模块是以非 Java 字节码的二进制代码形式嵌入 Java 程序的,而这种二进制代码通常只能运行在编译生成它的平台上,所以整个 Java 程序的跨平台性能将受到限制或破坏,除非 native 方法引入的代码也是跨平台的。

3. 构造方法

构造方法和成员方法的区别
  A:格式区别
    构造方法和类名相同,并且没有返回类型,也没有返回值

普通成员方法可以任意起名,必须有返回类型,可以没有返回值。

​ B:作用区别
​    构造方法用于创建对象,并进行初始化值。
​    普通成员方法是用于完成特定功能的。

​ C:调用区别
​    构造方法是在创建对象时被调用的,一个对象建立,只调用一次相应构造函数
​    普通成员方法是由创建好的对象调用,可以调用多次


 成员方法的作用是访问和操作成员变量。程序的其它部分都是通过方法调用和对象进行交互。

 需要什么功能就去创建什么方法。然后去调用这个方法。方法的调用需要借助对象.方法名
  比如我在一个类创建了一个对象,这个对象想调用另一个类的方法

 方法必须定义在某个类中,定义格式:
  [权限修饰符] 返回值类型 方法名(0-n个“参数类型 参数名”){
     // 说明部分
     // 执行语句部分
     }
成员变量和成员方法没有顺序要求,在成员方法中可直接访问成员变量
在方法体中使用return语句返回具体的值,如果方法没有返回值(此时不需要return语句),则返回类型为void。
当定义的这个方法有返回值时,调用处可以方法返回值,如a.getNum(3,2);这里是调用处,则带着实际参数执行完方法后得到的值会返回给a.getNum(3,2),如果用c去接收int c = a.getNum(3,2)。C就等于这个返回值
 成员方法的调用
  对象名.方法名();

4. 抽象方法

1、抽象类
  被abstract修饰的类,包含抽象方法的类就是抽象类。

通过abstract方法定义规范,然后要求子类必须定义具体实现。通过抽象类,我们就可以做到严格限制子类的设计,使子类之间更加通用。(程序的可扩展和可维护性)

抽象类的特征:
  1.抽象类不能实例化,即不能用new来实例化抽象类。
  
  2.抽象类中包含有构造方法,但构造方法不能用来new实例,只能用来被子类调用。
  
  3.抽象类中可以包含成员变量,成员方法,静态方法,构造方法,final 修饰的方法,抽象方法
  
  4. 抽象类只能用来被继承。

2、抽象方法

使用abstract修饰的方法,没有方法体,只有声明。定义的是一种“规范”,就是告诉子类必须要给抽象方法提供具体的实现。

抽象方法的特征:

1.抽象方法不允许有方法体,只能以分号“;”结尾

2.有抽象方法的类只能定义成抽象类(含有抽象方法的类必须是抽象类)

3.抽象类中可以包含 0 个或多个抽象方法

4.抽象方法必须被子类实现

5.如果子类不能实现父类中的抽象方法,那么子类也必须是抽象类

/**
 * 抽象类
 */
abstract class Animal {
    abstract public void shout();  //抽象方法
    public Animal(){
        System.out.println("Animal类中的无参构造...");
    }
}
class Dog extends Animal { 
    //子类必须实现父类的抽象方法,否则编译错误
    public void shout() {
        System.out.println("汪汪汪!");
    }
    public Dog(){
        super();//调用直接父类的无参构造,系统默认调用(可以省略)
        System.out.println("Dog类中的无参构造...");
    }
}
class Cat extends Animal {
    public void shout() {
        System.out.println("喵喵喵!");
    }
}
/**
 * 如果子类不能实现父类中的抽象方法,那么子类也必须是抽象类
 */
abstract class Pig extends Animal{
	
}
/**
 * 测试抽象类
 */
public class TestAbstractClass {
    public static void main(String[] args) {
 //       Animal a = new Animal();//编译出错,抽象类不能实例化
        Animal a1 = new Dog();
        a1.shout();
        Animal a2 = new Cat();
        a2.shout();
    }
}

3.3 方法的重载与重写的区别

​重载:在同一类中。方法名相同,参数列表不同。重载可以改变返回类型。
定义了多个同名的方法,它们或有不同的参数个数或有不同的参数类型,则 称为方法的重载 (Overload) 。

重载(overloading) 是在一个类里面,方法名字相同,而参数不同。返回类型可以相同也可以不同。

每个重载的方法(或者构造函数)都必须有一个独一无二的参数类型列表。

最常用的地方就是构造器的重载。

重载规则:

被重载的方法必须改变参数列表(参数个数或类型不一样);
被重载的方法可以改变返回类型;
被重载的方法可以改变访问修饰符;
被重载的方法可以声明新的或更广的检查异常;
方法能够在同一个类中或者在一个子类中被重载。
无法以返回值类型作为重载函数的区分标准。

public class Overloading {
    public int test(){
        System.out.println("test1");
        return 1;
    }
 
    public void test(int a){
        System.out.println("test2");
    }   
 
    //以下两个参数类型顺序不同
    public String test(int a,String s){
        System.out.println("test3");
        return "returntest3";
    }   
 
    public String test(String s,int a){
        System.out.println("test4");
        return "returntest4";
    }   
 
    public static void main(String[] args){
        Overloading o = new Overloading();
        System.out.println(o.test());
        o.test(1);
        System.out.println(o.test(1,"test3"));
        System.out.println(o.test("test4",1));
    }
}

​重写:在不同类中(子父类中)。
​ 方法声明相同(返回类型,方法名,参数列表均相同)。
​ 重写需要注意:
​ 子类方法的访问权限要大于等于父类方法的访问权限。
​ 静态只能重写静态。但是这种情况一般不会出现。

重写是子类对父类的允许访问的方法的实现过程进行重新编写, 返回值和形参都不能改变。即外壳不变,核心重写!

重写的好处在于子类可以根据需要,定义特定于自己的行为。 也就是说子类能够根据需要实现父类的方法。

重写方法不能抛出新的检查异常或者比被重写方法申明更加宽泛的异常。例如: 父类的一个方法申明了一个检查异常 IOException,但是在重写这个方法的时候不能抛出 Exception 异常,因为 Exception 是 IOException 的父类,只能抛出 IOException 的子类异常。

在面向对象原则里,重写意味着可以重写任何现有方法。实例如下:


class Animal
{
	//要被重写的方法
	public  String eat()
	{
		System.out.println("animal eatting");

		return "100";
	}
}

class Cat extends Animal
{
	//重写方法
	//两同:方法名相同、参数列表相同
	public String eat()
	{
		System.out.println("cat eatting thing");

		return "110";
	}
}

public class MainTest
{
	public static void main(String[]args)
	{
		Cat t=new Cat();
		t.eat();
	}
}

方法的重写规则
参数列表与被重写方法的参数列表必须完全相同。
  
  返回类型与被重写方法的返回类型可以不相同,但是必须是父类返回值的派生类(java5 及更早版本返回类型要一样,java7 及更高版本可以不同)。
 
  访问权限不能比父类中被重写的方法的访问权限更低。例如:如果父类的一个方法被声明为 public,那么在子类中重写该方法就不能声明为 protected。

  • 父类的成员方法只能被它的子类重写。

  • 声明为 final 的方法不能被重写。

  • 声明为 static 的方法不能被重写,但是能够被再次声明。

  • 子类和父类在同一个包中,那么子类可以重写父类所有方法,除了声明为 private 和 final 的方法。

  • 子类和父类不在同一个包中,那么子类只能够重写父类的声明为 public 和 protected 的非 final 方法。

  • 重写的方法能够抛出任何非强制异常,无论被重写的方法是否抛出异常。但是,重写的方法不能抛出新的强制性异常,或者比被重写方法声明的更广泛的强制性异常,反之则可以。

  • 构造方法不能被重写。

  • 如果不能继承一个方法,则不能重写这个方法。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值