Java基础-类与对象(下)

 (创作不易,感谢有你,你的支持,就是我前行的最大动力,如果看完对你有帮助,请留下您的足迹)

目录

一、Java修饰符

访问控制修饰符

默认访问修饰符-不使用任何关键字

私有访问修饰符-private

公有访问修饰符-public

受保护的访问修饰符-protected

访问控制和继承

非访问修饰符

static修饰符

二、静态方法

调用方法

三、静态代码块

实例初始化块

多重实例初始化 

静态初始化块 


一、Java修饰符

Java语言提供了很多修饰符,主要分为以下两类:

  • 访问修饰符

  • 非访问修饰符

修饰符用来定义类、方法或者变量,通常放在语句的最前端。我们通过下面的例子来说明:

public class className {
   // ...
}
private boolean myFlag;
static final double weeks = 9.5;
protected static final int BOXWIDTH = 42;
public static void main(String[] arguments) {
   // 方法体
}

访问控制修饰符

Java中,可以使用访问控制符来保护对类、变量、方法和构造方法的访问。Java支持4种不同的访问权限。

默认的,也称为default,在同一包内可见,不使用任何修饰符。

私有的,以private修饰符指定,在同一类内可见。

共有的,以public修饰符指定,对所有类可见。

受保护的,以protected修饰符指定,对同一包内的类和所有子类可见。

默认访问修饰符-不使用任何关键字

使用默认访问修饰符声明的变量和方法,对同一个包内的类是可见的。接口里的变量都隐式声明为public static final,而接口里的方法默认情况下访问权限为public。

实例:

如下例所示,变量和方法的声明可以不使用任何修饰符。

String version = "1.5.1";
boolean processOrder() {
   return true;
}

私有访问修饰符-private

私有访问修饰符是最严格的访问级别,所以被声明为private的方法、变量和构造方法只能被所属类访问,并且类和接口不能声明为private。

声明为私有访问类型的变量只能通过类中公共的getter方法被外部类访问。

Private访问修饰符的使用主要用来隐藏类的实现细节和保护类的数据。

下面的类使用了私有访问修饰符:

public class Logger {
   private String format;
   public String getFormat() {
      return this.format;
   }
   public void setFormat(String format) {
      this.format = format;
   }
}

实例中,Logger类中的format变量为私有变量,所以其他类不能直接得到和设置该变量的值。为了使其他类能够操作该变量,定义了两个public方法:getFormat() (返回format的值)和setFormat(String)(设置format的值)

公有访问修饰符-public

被声明为public的类、方法、构造方法和接口能够被任何其他类访问。

如果几个相互访问的public类分布在不同的包中,则需要导入相应public类所在的包。由于类的继承性,类所有的公有方法和变量都能被其子类继承。

以下函数使用了公有访问控制:

public static void main(String[] arguments) {
   // ...
}

Java程序的main() 方法必须设置成公有的,否则,Java解释器将不能运行该类。

受保护的访问修饰符-protected

被声明为protected的变量、方法和构造器能被同一个包中的任何其他类访问,也能够被不同包中的子类访问。

Protected访问修饰符不能修饰类和接口,方法和成员变量能够声明为protected,但是接口的成员变量和成员方法不能声明为protected。

子类能访问Protected修饰符声明的方法和变量,这样就能保护不相关的类使用这些方法和变量。

下面的父类使用了protected访问修饰符,子类重载了父类的openSpeaker()方法。

class AudioPlayer {
   protected boolean openSpeaker(Speaker sp) {
      // 实现细节
   }
}

class StreamingAudioPlayer {
   boolean openSpeaker(Speaker sp) {
      // 实现细节
   }
}

如果把openSpeaker()方法声明为private,那么除了AudioPlayer之外的类将不能访问该方法。如果把openSpeaker()声明为public,那么所有的类都能够访问该方法。如果我们只想让该方法对其所在类的子类可见,则将该方法声明为protected

访问控制和继承

请注意以下方法继承的规则:

  • 父类中声明为public的方法在子类中也必须为public。

  • 父类中声明为protected的方法在子类中要么声明为protected,要么声明为public。不能声明为private。

  • 父类中声明为private的方法,不能够被继承。

非访问修饰符

为了实现一些其他的功能,Java也提供了许多非访问修饰符。

static修饰符,用来创建类方法和类变量。

final修饰符,用来修饰类、方法和变量,final修饰的类不能够被继承,修饰的方法不能被继承类重新定义,修饰的变量为常量,是不可修改的。

abstract修饰符,用来创建抽象类和抽象方法。

synchronized和volatile修饰符,主要用于线程的编程。

static修饰符

  • 静态变量:

    static关键字用来声明独立于对象的静态变量,无论一个类实例化多少对象,它的静态变量只有一份拷贝。静态变量也被称为类变量。局部变量不能被声明为static变量。

  • 静态方法:

    static关键字用来声明独立于对象的静态方法。静态方法不能使用类的非静态变量。静态方法从参数列表得到数据,然后计算这些数据。

对类变量和方法的访问可以直接使用classname.variablename和classname.methodname的方式访问。

如下例所示,static修饰符用来创建类方法和类变量。

public class InstanceCounter {
   private static int numInstances = 0;
   protected static int getCount() {
      return numInstances;
   }

   private static void addInstance() {
      numInstances++;
   }

   InstanceCounter() {
      InstanceCounter.addInstance();
   }

   public static void main(String[] arguments) {
      System.out.println("Starting with " +
      InstanceCounter.getCount() + " instances");
      for (int i = 0; i < 500; ++i){          
         new InstanceCounter();           
      }       
      System.out.println("Created " +       InstanceCounter.getCount() + " instances");            
   } 
}

以上实例运行编辑结果如下

Started with 0 instances
Created 500 instances

二、静态方法

类可以有两种类型的方法:实例方法和类方法实例方法和类方法也分别称为非静态方法和静态方法。

实例方法用于实现类的实例的行为。实例方法只能在类的实例的上下文中调用。

类方法用于实现类本身的行为。类方法总是在类的上下文中执行。

静态修饰符用于定义类方法。方法声明中缺少静态修饰符,使得该方法成为一个实例方法。

以下是声明一些静态和非静态方法的示例:

// A  static or  class method 
static void  aClassMethod()  {
    
}

// A  non-static or  instance method 
void  anInstanceMethod()  {

}

注意

当调用类的静态方法时,该类的实例可能不存在。因此,不允许从静态方法内部引用实例变量。

类定义一加载到内存中,类变量就存在。类定义在创建类的第一个实例之前加载到内存中。

类方法或静态方法只能引用类的变量或类的静态变量。实例方法或非静态方法可以引用类变量以及类的实例变量。

以下代码演示了在方法中可访问的类字段的类型。

public class Main {
  static int m = 100; // A static variable
  int n = 200; // An instance variable

  // Declare a static method
  static void printM() {

    /*
     * We can refer to only static variable m in this method because you are
     * inside a static method
     */

    System.out.println("printM() - m   = " + m);

  }

  // Declare an instance method
  void printMN() {
    /* We can refer to both static and instance variables m and n in this method */
    System.out.println("printMN() - m   = " + m);
    System.out.println("printMN() - n  = " + n);
  }
}

调用方法

在方法的主体中执行代码称为调用(或调用)方法。

实例方法和类方法以不同方式调用。

使用点表示法在类的实例上调用实例方法。

<instance reference>.<instance method name>(<actual parameters>)

在调用该类的实例方法之前,我们必须引用一个类的实例。

以下代码显示如何调用Main类的printMN()实例方法:

// Create an  instance of  Main class  and
// store its  reference in mt reference variable
Main mt = new Main();

// Invoke  the   printMN() instance  method  using the   mt reference variable 
mt.printMN();

要调用类方法,请使用带有名称的点表示法。

下面的代码调用Main类的printM()类方法:

// Invoke  the   printM() class  method
Main.printM();

属于一个类的属性也属于该类的所有实例。我们还可以使用该类的实例的引用来调用类方法。

Main mt = new Main();
mt.printM(); // Call the   class method  using an  instance mt

使用类名调用类方法比使用实例引用更直观。

三、静态代码块

实例初始化块

实例初始化块用于初始化类的对象。

一个实例初始化程序只是一个类的代码块,但在任何方法或构造函数之外。

实例初始值设定程序没有名称。它的代码只是放置在一个开放大括号和闭包。

下面的代码展示了如何为Test类声明一个实例初始化器。

注意,实例初始化程序在实例上下文中执行,并且关键字this在实例初始化程序中可用。

class Test {
  private int num;
  // An instance initializer
  {
    this.num = 101;

    /* Other code for the instance initializer*/
  }

  /* Other code for Test class*/
}

多重实例初始化 

我们可以有一个类的多个实例初始化器。对于我们创建的每个对象,它们都以文本顺序自动执行。

所有实例初始值的代码在任何构造函数之前执行。

下面的代码演示了构造函数和实例初始化函数的执行顺序。

public class Main {
  {
    System.out.println("Inside instance initializer 1.");
  }

  {
    System.out.println("Inside instance initializer 2.");
  }

  public Main() {
    System.out.println("Inside  no-args constructor.");
  }

  public static void main(String[] args) {
    Main m = new Main();
  }
}

上面的代码生成以下结果。

实例初始化程序不能有return语句。

静态初始化块 

静态初始化块也称为静态初始化器。它类似于实例初始化块。

它用于初始化一个类。每个对象执行一个实例初始化器,而当类定义被加载到JVM中时,只对一个类执行一次静态初始化器。

我们需要在其声明的开头使用static关键字。

我们可以在类中有多个静态初始化器。所有静态初始化器都按文本出现的顺序执行,并在任何实例初始化器之前执行。

以下代码演示了何时执行静态初始化程序。

public class Main {
  private static int num;
  {// An instance initializer
    System.out.println("Inside instance initializer.");
  }
  // A static initializer. Note the use of the keyword static below.
  static {
    num = 2014;
    System.out.println("Inside static initializer.");
  }

  // Constructor
  public Main() {
    System.out.println("Inside constructor.");
  }

  public static void main(String[] args) {
    System.out.println("Inside  main() #1.   num: " + num);
    // Declare a reference variable of the class
    Main si;
    System.out.println("Inside  main() #2.   num: " + num);
    new Main();    // Create an object

    System.out.println("Inside  main() #3.   num: " + num);
    new Main();// Create another object
  }
}

上面的代码生成以下结果。

评论 17
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小周不想卷

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值