Java(static实际运用)
检测生成对象的个数。
提示:共用变量与构造方法
class A
{
private static int i=0;//静态变量是共用的。
//i是私有的是为了防止有其他方式更改i的值。
public A()//每创建一个对象都会调用一次构造方法。
{
i++;//因为i是静态的,所以每个对象中的i都是同一个i。
//每创建一个对象都会使i的值加1
}
public static int getCnt()//静态方法可以随时调用。更方便。
{
return i; //返回的是A对象的个数;
}
}
public class Test1
{
public static void main(String[] args)
{
A aa1 = new A();
A aa2 = new A();
//创建了两个对象。
System.out.printf("创建的对象个数为%d\n",A.getCnt());
}
}
例子2:
class A
{
private int i;
private static int cnt = 0; //静态变量是共用的。
//cnt是私有的是为了防止有其他方式更改i的值。
public A()//每创建一个对象都会调用一次构造方法。
{
cnt++;//因为cnt是静态的,所以每个对象中的cnt都是同一个cnt。
//每创建一个对象都会使cnt的值加1
}
public A(int i)
{
this.i = i;
cnt++;//不管调用那个构造方法 都会使cnt加1
}
public static int getCnt()//静态方法可以随时调用。更方便。
{
return cnt;
//return返回的是当前
}
}
public class Test1
{
public static void main(String[] args)
{
System.out.printf("当前时刻对象的个数是%d\n", A.getCnt());
A aa1 = new A();
System.out.printf("当前时刻对象的个数是%d\n", A.getCnt());
A aa2 = new A();
//创建了两个对象。
System.out.printf("当前时刻对象的个数是%d\n", A.getCnt());
}
}
static的用途2。
利用static控制某一个类只能产生一个对象。
类与类包含的关系。
class A
{
public int j = 20;
}
class B
{
public int i = 10;
//定义了一个数据类型为int的变量i,i里面存放的是10。
public A aa = new A();//不会报错。说明一个类中的属性也可以是个类对象。
//这里在类和对象的时候说过,可以看做是
//定义了一个数据类型为A的变量aa,aa里面存放的是A类。
//aa是B的属性。
}
public class Test1
{
public static void main(String[] args)
{
B bb = new B();
System.out.printf("%d\n",bb.aa.j);
}
}
//本程序证明了:一个类中的属性也可以是一个类对象。
是否能在类中定义一个自身对象?
例子:
class A
{
public int i = 20;
public A aa = new A();//不会报错。说明可以在A类中定义一个aa对象。
//这种方式很少用,只有在利用static控制某一个类只能产生一个对象的时候才会用到。
}
public class Test1
{
public static void main(String args[])
{
A aa = new A();//语法上不会报错,但是new一个对象的时候,会报错。
//是因为无限的在A类中无限new对象。
//所以我们要找一个让它只创建一次的方法。
}
}
方法1:
class A
{
public int i = 20;
public static A aa = new A();//这个aa存放在data segment里面。
//定义一个静态的属性,这样aa就只能在里面定义一次了。
}
public class Test1
{
public static void main(String args[])
{
A aa = new A();//这个aa存放在堆里面
System.out.printf("%d\n", aa.i);
//这是输出通过A类new出的aa中的i。
System.out.printf("%d\n", aa.aa.i);
//这是输出通过A类new出的aa中的又通过A类new出的静态的aa中的i。
System.out.printf("%d\n", A.aa.i);
//这是输出通过A类new出的aa中的又通过A类new出的静态的aa中的i。
//因为这个对象属性是静态的,所以可以直接通过类名访问
//但是。静态aa中的i不是静态的,所以要通过对象名访问。
//这样的话aa对象中的静态aa对象,就只能创建一次了。
//不管你通过A类new多少个对象,对象中的静态aa就只会创建一次。
//检验,定义两个对象,然后改变对象中静态对象中的属性。
//另一个对象中的静态对象的属性是否也改变,如果改变,则说明这个对象是唯一的。
A aa1 = new A();
A aa2 = new A();
aa1.aa.i=99;//改变aa1中的aa中的i的值
System.out.printf("%d\n", aa2.aa.i);//99
//改变aa2中的aa中的i的值,说明创建一个唯一对象成功。
aa1.i=80;
System.out.printf("%d\n", aa1.aa.i);
//证明了aa1中的i与静态aa中的i不是同一个i.
//不过有个缺点,就是会重复定义一遍类中的成员。浪费内存。
//而且运用起来比较麻烦。
}
}
方法2:创建一个私有的唯一的对象。
禁用new;禁止用new来生成对象。提示:构造方法与访问修饰符
例子:
class A
{
public int i = 10;
private A()//定义一个私有的构造方法。
{
//new一个对象的时候,一定会调用构造方法。如果构造方法是私有的。
//就无法调研构造方法了这时候new对象的时候就会报错。
}
}
public class Test1
{
public static void main(String args[])
{
A aa = new A();//error 会报错,因为构造方法是私有的无法访问。
}
}
不浪费内存的方法。
通过接口来直接访问该属性
例子:
class A
{
public int i = 20;
private static A aa = new A();//注意这里权限改成了私有的
//因为是static类型的aa对象,不用new也能使用。
private A()//定义一个私有的构造方法来禁止new对象。
{
}
public static A getA()//定义一个公有的静态的方法当接口
{//为什么是公有的?方便在其他类中调用该方法
//为什么是静态的?因为上面的构造方法已经禁止了new对象。不然无法调用该方法
return aa;//返回值为对象aa
//因为aa是static类型的,可以直接使用。
}
}
public class Test1
{
public static void main(String[] args)
{
//A aa1 = new A();//error。因为构造方法是私有的,不能new对象。
//A aa1 = aa;//error。因为aa是私有的
A aa1 = A.getA();//通过提供的接口直接把A中的静态aa直接赋给aa1.
A aa2 = A.getA();//定义一个aa2对象,用来存储aa。
//检测:aa1与aa2是否存储的是同一个对象
aa1.i=99;//把aa1中的i的值改成99
//如果aa2中的值也为99,则说明他们存储的是同一个对象。
System.out.printf("%d\n",aa2.i);
}
}
提问1:既然接口方法返回的是同一个aa,
那么private static A aa = new A();中的static是否可以去掉?
答案:不可以去掉。
因为接口是static类型的。静态类型方法不能访问非静态类型成员。
提问2:方法2中的私有制构造函数可以去掉吗?
答案:可以。
去掉构造函数之后,可以通过new一个对象来访问对象aa但是,要非私有制的才能访问。
不过加上最好,防止浪费内存。