---------------------- <a href="http://edu.csdn.net"target="blank">ASP.Net+Android+IOS开发</a>、<a href="http://edu.csdn.net"target="blank">.Net培训</a>、期待与您交流! ----------------------
一、static关键字描述
是一个修饰符,用于修饰成员变量和成员函数,被其修饰后存放位置就不在堆内存中了,且被修饰的内容被对象所共享,同时提供了一种调用方式,类名.xx,
二、static特点
随着类的加载而加载,随着类的消失而消失;优先对象存在;被所有对象共享;可以直接被类名调用
class StaticTest
{
int a = 0;
static int b = 0;
public static void main(String[] args)
{
StaticTest st1 = new StaticTest();
st1.a++;
st1.b++;
System.out.println(" st1");
System.out.println(" st1.a=" st1.a);
System.out.println(" st1.b="st1.b);
StaticTest st2 = new StaticTest();
st2.a++;
st2.b++;
System.out.println(" st2");
System.out.println(" st2.a=" st2.a);
System.out.println(" st2.b="st2.b);
}
}
以上程序打印结果为:st1、st1.a=1、st1.b=1、st2、st2.a=1、st2.b=2,由st1.b=1和st2.b=2看出st1和st2这两个实例共享被static修饰的成员变量b,并且b在内存中只有一份,任意对象对其进行修改都会导致所有对象的b值发生改变。
三、注意事项
静态方法只能访问静态成员;静态方法中不可以定义this,super关键字,因静态优先于对象存在,所以静态方法不可出现this关键字和super关键字。
class StaticTest
{
int a = 1;
static int b = 2;
public void show()
{
System.out.println(a);//编译通过
System.out.println(b);//编译通过
}
public static void print_1()
{
System.out.println(a);//编译失败
}
public static void print_2()
{
System.out.println(b);//编译通过
}
}
StaticTest类中show方法编译通过,可以看出被static修饰的成员变量可以被非静态所访问,print_1方法编译失败而print_2方法则能编译通过说明静态只能访问静态,print_2为静态方法因而只能访问被static修饰的b。
四、静态的使用时机
1,对象中出现共享数据时(不是共同属性)被静态修饰,而对象中特有数据定义成非静态存在于堆内存中
2,当功能内没有访问到非静态数据时,那么该功能定义成静态
3,示例演示定义一个ArrayTools类封装用于对数组的操作的方法,另一类ArrayToolsDemo对数组进行操作
ArrayTools类
public class ArrayTool
{
//获取最大值。
public static int getMax(int[] arr)
{
int max=0;
for(int x=1;x<arr.length;x++)
{
if(arr[max]<arr[x])
{
max=x;
}
}
//System.out.println("arr[max]="+arr[max]);
return arr[max];
}
//获取最小值。
public static int getMin(int[] arr)
{
int min=0;
for(int x=1;x<arr.length;x++)
{
if(arr[min]>arr[x])
{
min=x;
}
}
return arr[min];
}
//打印数组中的元素。
public static void printArray(int[] arr)
{
System.out.print("[");
for(int x=0;x<arr.length;x++)
{
if(x!=arr.length-1)
{
System.out.print(arr[x]+",");
}else{
System.out.println(arr[x]+"]");
}
}
}
}
ArrayToolsDemo类
class ArrayToolDemo
{
public static void main(String[] args)
{
int[] arr= new int[]{4,8,7,6,9,5};
ArrayTool.printArray(arr);
ArrayTool.selectSort(arr);
ArrayTool.printArray(arr);
}
}
由于ArrayTool类仅对数组进行操作,方法也并不需要去访问任何非静态成员因而将其所有方法声明为static,ArrayTool类可以通过类名调用的方式来使用这些方法,因而在ArrayToolsDemo中就不必去创建ArrayTool对象的实例,直接通过类名调用的方式使用方法操作数组,因此当我们将ArrayTool的构造函数私有后,就可以提供公共的静态方法给外部使用,而外部只能通过类名调用的方式使用功能而不能创建对象,使程序更加安全简洁。
五、静态代码块
1,格式:static{静态代码块执行的语句}
2,特点:随类的加载而加载,只执行一次,优先于主函数
class StaticCode
{
static{System.out.println("a");}
}
class StaticCodeDemo
{
static{System.out.println("b");}
public static void main(String[] args)
{
new StaticCode();
new StaticCode();
System.out.println("over");
}
static{System.out.println("c");}
}
打印结果::b c a over
六、关于主函数
1,主函数被static修饰因而主函数是静态的随着类的加载而加载
2, 它是一个特殊的函数,作为程序的入口,可以被jvm调用
3, 格式固定,被jvm识别
4, 可以被重载,但jvm只调用参数为String[]args的函数
5, Jvm调用主函数时可以传入参数,格式为: java类名 字符串1字符串1……
七、static的应用——单例设计模式
用于解决一个类在内存只存在一个对象
1,创建单例类的步骤
1.1,将构造函数私有
1.2,在类中创建一个私有静态的本类对象
1.3,提供一个公共的静态方法用于获取该对象
2,创建单例类的第一种方式
class Single
{
private static final Single s = new Single();
private Single(){}
public static Single getInstance()
{
return s;
}
}
3,创建单例类的第二种方式
class Single
{
private static Single s = null;
private Single(){}
public static Single getInstance()
{
if(s==null)
{
synchronized(Single.class)
{
if(s==null)
return s=new Single();
}
}
return s;
}
}
第二种方式在创建单例类时加入了同步,因为第二种方式中在多线程的情况下出现了多条语句操作同一个线程的共享数据即s,当一个线程对多条语句只执行了一部分而没有执行完所有语句,而这时另一个线程进来执行,从而导致共享数据错误。由于getInstance方法是静态方法,因而同步代码块中的锁使用的是Single.class这个字节码文件对象。
八、内部类使用static
1,当内部类定义在局部时不能使用static修饰,因为static是成员修饰符
2,当内部类定义在成员位置时可以被static修饰,并且被修饰后只能访问外部类的静态成员
3,当内部类中定义了类静态成员,那么该内部类必须被声明为静态的。
---------------------- <a href="http://edu.csdn.net"target="blank">ASP.Net+Android+IOS开发</a>、<a href="http://edu.csdn.net"target="blank">.Net培训</a>、期待与您交流! ----------------------
详细请查看:<a href="http://edu.csdn.net" target="blank">http://edu.csdn.net</a>