如果现在希望一个属性被所有对象所共同拥有,则可以将其声明为static类型,声明static类型的属性或方法之后此属性或方法也成为类方法,可以由类型直接调用。
使用static声明的属性被称为全局变量,是所有对象共享的,简单来说就是在一个对象中改变了此全局属性,则其他对象中的属性也会改变,代码如下:
class Person { String name; int age; static String country="A城"; //使用static声明全局变量 public Person(String name,int age){ this.name=name; this.age=age; } public void getInfo(){ System.out.println("姓名是:"+name+"年龄是:"+age+"城市是:"+country); } } public class staticDemo01 { public static void main(String args[]){ Person per1=new Person("张三",20); Person per2=new Person("李四",40); Person per3=new Person("王五",30); per1.getInfo(); per2.getInfo(); per3.getInfo(); System.out.println("---------修改之前-----------"); //在静态的方法中只能调用静态的属性 Person.country="B城"; //只有当country属性为static时才能够调用,否则会出现无法从静态上下文中引用非静态的变量的错误 per1.getInfo(); per2.getInfo(); per3.getInfo(); System.out.println("---------修改之前-----------"); } }
每一个对象都拥有各自的堆栈空间,堆内存空间中保存每个对象的各自的属性,但是所有的使用static关键字声明的属性是保存在了全局数据区之中,所有的对象指向全局数据区域中的一个内容,所有当一个对象修改了此属性之后,所有的对象的内容都会发生变化。
Java中的内存区域:
·栈内存:可以保存对象的名称,(保存,访问的堆内存的地址)
·堆内存:保存每个对象的具体属性。
·全局数据区:保存static类型的属性。
·全局代码区:保存所有方法的定义。
如果一个方法使用了static关键字声明,则此方法可以由类名称直接调用,即:类名称.方法
class Person { static String name="张三"; static int age=20; static String country="A城"; //使用static声明全局变量 public Person(String name,int age){ this.name=name; this.age=age; } public static void getInfo(){ System.out.println("姓名是:"+name+"年龄是:"+age+"城市是:"+country); } } public class staticDemo02 { public static void main(String args[]){ Person.getInfo(); } }
注意:使用static声明的方法,不能调用非static的属性或方法。就是说假如以上代码中Person类中name和age属性没有声明为static类型,则会出现错误。原因是因为static属性或方法可以在对象没有被实例化之前就可以调用了。
统计一个类中到底有多少个类被实例化:
class Person { static int count=0; public Person(){ count++; //只要有一个对象产生就自增 System.out.println("有"+count+"个对象被实例化了!"); } } public class staticDemo03 { public static void main(String args[]){ new Person(); //1 new Person(); //2 new Person(); //3 } }
自动编名操作:
class Person { String name; private static int count=0; public Person(String name){ count++; this.name="DEMO-"+count; } public void getName(){ System.out.println("姓名是:"+name); } } public class staticDemo04 { public static void main(String args[]){ new Person("").getName(); //DEMO-1 new Person("").getName(); //DEMO-2 new Person("").getName(); //DEMO-3 } }
以上应用在以后的开发中会有所实现。
解释:public static void main(String args[ ])
public:表示此方法可以被外部调用。
static:表示此方法可以由类名称直接调用。
void :主方法是程序的起点,所以不需要任何的返回值。
main:系统规定好默认调用的方法名称,执行的时候,默认找到main方法名称。
String args[ ] 表示的是运行时的参数,参数传递的形式:java类名称 参数1参数2参数3
看如下的代码:
public class staticDemo05 { public static void main(String args[]){ for(String x:args){ System.out.println(x); } } }
该代码在执行时必须传入参数,格式:java类名称 参数1 参数2参数3….参数个数不限,但必须用“ ”(空格)隔开,输出为输入的内容。
代码2:对传入的参数进行判断:
public class staticDemo06 { public static void main(String args[]){ if(args.length!=3){ System.out.println("参数格式不正确,程序退出!"); System.exit(1); } for(String x:args){ System.out.println(x); } } }
参数个数不是3,程序将自动退出。
所谓的代码块是指使用“{ }”括起来的一段代码,根据位置不同,代码块可以分为四种:普通代码块、构造块、静态代码块、同步代码块。
直接定义在方法中的代码称为普通代码块:
public class codeDemo01 { public static void main(String args[]){ { //普通代码块 int x=30; //属于一个局部变量 System.out.println("普通代码块-----> x ="+x); } int x=100; //与局部变量名称相同 想对来说就成了全局变量 System.out.println("普通代码块之外-----> x ="+x); } }
将代码块直接定义在类中,则称为构造块。构造块的内容会优先于构造方法的执行,且执行多次,当有实例化对象的时候执行
class Demo { { //构造块 System.out.println("构造块"); } public Demo(){ System.out.println("构造方法"); } } public class codeDemo02{ public static void main(String args[]){ new Demo(); //实例化对象 new Demo(); //实例化对象 new Demo(); //实例化对象 } }
直接使用static关键字声明的代码就称为静态代码块。
class Demo { { //构造块 System.out.println("构造块"); } static{ System.out.println("Person中的静态代码块"); } public Demo(){ System.out.println("构造方法"); } } public class codeDemo03{ static{ System.out.println("MAIN方法中的静态代码块"); } public static void main(String args[]){ new Demo(); //实例化对象 new Demo(); //实例化对象 new Demo(); //实例化对象 } }
如果主方法中存在静态代码块,则静态块优先于主方法的执行,如果是在普通的类中定义的代码块,优先于构造方法执行,不管有多少个实例化对象产生,静态代码块只执行一次,静态代码块的主要功能是为静态属性初始化值。
类的封装性不单单是体现在对属性的封装上,方法也是可以封装的,当然,在方法中也包含了对构造方法的封装,例如如下代码:
class Singleton { private Singleton(){ //使用private 私有化当前构造方法 System.out.println("对象被实例化了"); } } public class SingletonDemo01 { public static void main(String args[]){ Singleton sin=null; sin=new Singleton(); //出现错误,不能实例化 } }
此时的解决办法是在Singleton类内部进行实例化,然后定义为static这样在类的外部可以直接用类名.属性直接访问。代码如下:
class Singleton { static Singleton instance=new Singleton(); private Singleton(){ //使用private 私有化当前构造方法 System.out.println("对象被实例化了"); } } public class SingletonDemo02 { public static void main(String args[]){ Singleton sin=null; sin=Singleton.instance; //程序输出对象被实例化了 } }
但是以上的代码设计不是最合理的,最完美的写法:即(单例设计模式)
饿汉式单例模式:
class Singleton { //进来就进行实例化的饿汉 private static Singleton instance=new Singleton(); //私有化当前对象 private Singleton(){ //使用private 私有化当前构造方法 System.out.println("对象被实例化了"); } public static Singleton getInstance(){ //通过方法获得当前类实例化好的对象 return instance; } } public class SingletonDemo03 { public static void main(String args[]){ Singleton sin=null; sin=Singleton.getInstance(); //程序输出对象被实例化了 } }
懒汉式单例设计模式
class Singleton { //在方法中进行实例化的是懒汉 private static Singleton instance=null; //声明并私有化当前对象 private Singleton(){ //使用private 私有化当前构造方法 System.out.println("对象被实例化了"); } public static Singleton getInstance(){ //通过方法获得当前类实例化好的对象 instance=new Singleton(); return instance; } } public class SingletonDemo04 { public static void main(String args[]){ Singleton sin=null; sin=Singleton.getInstance(); //程序输出对象被实例化了 } }
使用单例设计模式的好处:
不管当前程序有多少个new关键字,假如要想得到Singleton类的对象,就必须要调用其getinstance方法,所以只会有一个实例被创建,而所有的对象都是隶属于该实例。现在了过多的对象被创建。其核心就是构造方法的私有化。