构造方法私有化及对象数组
一. 构造方法私有化
1. 问题的引出
类的封装性不只体现在对属性的封装上,实际上方法也是可以进行封装的,当然,在方法封装中也包括了对构造方法的封装。
例:
class Singleton{
private Singleton(){
}
public void print(){
System.out.println("Hello World!");
}
}
从之前的讲解中可以清楚的知道,一个类想使用,则必须要有实例化的对象,现在要想调用Singleton类中的print()方法则一定要首先产生Singleton的实例化对象,但是由于此时构造方法被私有化了,所以如果按照如下的程序编写,则肯定会出现错误。
【错误代码,直接实例化Singleton类对象】
public class SingletonDemo02
{
public static void main(String[] args){
Singleton s1=null;
s1=new Singleton();
s1.print();
}
}
程序运行的结果为:
SingletonDemo02.java:13: 错误: Singleton()可以在Singleton中访问private
s1=new Singleton();
^
1 个错误
从上述错误提示中可以发现,程序是在使用new关键字实例化对象时出现了错误,而对于声明对象则没有任何的错误,那么该如何解释那?
封装是指一切外部不可见性,那么就意味着在外部根本无法调用被封装的构造方法,既然外部不能调用,那么在内部码?
【在内部产生Singleton的对象】
class Singleton{
static Singleton instance=new Singleton();
private Singleton(){
}
public void print(){
System.out.println("Hello World!");
}
}
以上的程序编译后,不会出现任何错误,可以正常的完成instance对象的实例化,即此时的问题在于如何将内部的instance对象传递到类的外部,这样外部就可以通过instance来实例化其他的Singleton的对象。那么对象到底该如何取?
2. 问题的解决
在前面讲解static关键字时曾经讲过,static类型的属性可以由类名称直接调用,所以此时可以将instance属性声明为static类型,这样就可以通过类名称直接调用。
【将instance声明为static类型】
class Singleton{
static Singleton instance=new Singleton();
private Singleton(){
}
public void print(){
System.out.println("Hello World!");
}
}
public class SingletonDemo04
{
public static void main(String[] args){
Singleton s1=null;
s1=Singleton.instance;
s1.print();
}
}
运行结果为:
Hello World!
由运行结果可以发现,程序成功地取得了Singleton的实例化对象并调用了print()方法。但是这样做本身也存在着问题,因为类中的属性必须封装,所以此处应该将instance属性进行封装,而封装后必须通过方法取得,但是因为instance属性属于静态属性,所以此处必须声明一个静态方法,这样就可以被类名称直接调用。
【使用静态方法,取得Singleton类的实例】
class Singleton{
private static Singleton instance=new Singleton();
private Singleton(){
}
public static Singleton getInstance(){
return instance;
}
public void print(){
System.out.println("Hello World!");
}
}
public class SingletonDemo05
{
public static void main(String[] args){
Singleton s1=Singleton.getInstance();
Singleton s2=Singleton.getInstance();
Singleton s3=Singleton.getInstance();
s1.print();
s2.print();
s3.print();
}
}
运行结果为:
Hello World!
Hello World!
Hello World!
- 程序的意义
在以上的程序中可以发现虽然声明了3个对象,但是实际上所有的对象都只使用一个instance引用,也就是说,此时不管外面如何使用,最终结果程序中也只有一个Singleton类的实例化对象存在,在设计模式中称为单例模式,即无论程序怎么运行,Singleton类永远只有一个实例化对象存在。
只要将构造方法私有化,就可以控制实例化对象的产生。
二. 对象数组
对象数组的概念其实并不复杂,所谓的对象数组,就是指包含了一组相关对象的集合,但是在对象数组的使用中读者一定要清楚一点:数组一定要先开辟空间,但是因为其是引用数据类型,所以数组中的每一个对象默认值都是null值,则在使用数组对象中的每一个对象都必须分别进行实例化操作。
【对象数组的声明】
类 对象数组名称[]=new 类[数组长度];
【声明一个对象数组】
class Person
{
private String name;
public Person(String name ){
this.name=name;
}
public String getName(){
return this.name;
}
}
public class ObjectArrayDemo01
{
public static void main(String args[]){
Person per[]=new Person[3];
System.out.println("=======声明数组=======");
for(int i=0;i<per.length;i++){
System.out.println(per[i]+"、");
}
per[0]=new Person("张三");
per[1]=new Person("李四");
per[2]=new Person("王五");
System.out.println("\n===========对象实例化==========");
for(int j=0;j<per.length;j++){
System.out.println(per[j].getName()+"、");
}
}
}
运行结果为:
=======声明数组=======
null、
null、
null、
===========对象实例化==========
张三、
李四、
王五、
与数组初始化的方式一样,对象数组也分为静态初始化和动态初始化。以上操作属于数组的动态初始化,静态初始化代码如下,
【对象数组的静态初始化】
class Person{
private String name ; // 姓名属性
public Person(String name){ // 通过构造方法设置内容
this.name = name ; // 为姓名赋值
}
public String getName(){
return this.name ; // 取得姓名
}
};
public class ObjectArrayDemo02{
public static void main(String args[]){
// 声明一个对象数组,里面有三个对象,使用静态初始化方式完成
Person per[] = {new Person("张三"),new Person("李四"),new Person("王五")} ;
System.out.println("\n============== 数组输出 =================") ;
for(int x=0;x<per.length;x++){ // 循环输出
System.out.print(per[x].getName() + "、") ; // 此时,已经实例化完成了,所以会直接打印出姓名
}
}
};
运行结果为:
============== 数组输出 =================
张三、李四、王五、
程序中在声明对象数组是采用了静态初始化的方式,然后采用循环的方式依次输出对象数组中的每一个元素。
注:主方法中String agrs[]就是对象数组。在主方法中,可以使用String args[]接收初始化参数,实际上这里的String本身就是一个类,所以在主方法中的参数本身就是以对象数组的形式出现的。