static是Java中定义的一个关键字,主要是描述全局的概念,所以利用static关键字可以定义属性和方法。但是在百分之九十的情况下,开发代码很少会直接编写static。
利用static定义属性
class Person{
private String name;
private int age;
String country = "中华人民共和国";//此属性暂时不封装
public Person(String name,int age){
this.name=name;
this.age=age;
}
public String getInfo(){
return "姓名:"+this.name+",年龄:"+this.age+",国家:"+this.country;
}
}
public class Hello {
public static void main(String args[]){
Person perA = new Person("小胖",10);
Person perB = new Person("小壮",20);
Person perC = new Person("小不点",10);
System.out.println(perA.getInfo());
System.out.println(perB.getInfo());
System.out.println(perC.getInfo());
}
}
但是对于以上的程序的内存关系中就会发现问题。
如果时光倒退回唐朝,这个时候代码维护难度就比较大,造成这种问题的原因是类中的普通属性是每个对象都独自拥有的,所以这样的设计明显不符合当前的环境,所以最好的做法是将国家这个属性设置为公共属性,所有的对象都可以共享此属性,如果要实现这样的操作,就可以通过static关键字来进行定义。
范例:使用static关键字来定义
class Person{
private String name;
private int age;
static String country = "中华人民共和国";//此属性暂时不封装
public Person(String name,int age){
this.name=name;
this.age=age;
}
public String getInfo(){
return "姓名:"+this.name+",年龄:"+this.age+",国家:"+this.country;
}
}
public class Hello {
public static void main(String args[]){
Person perA = new Person("小胖",10);
Person perB = new Person("小壮",20);
Person perC = new Person("小不点",10);
perA.country="中国-唐朝";//修改了一个对象的属性
System.out.println(perA.getInfo());
System.out.println(perB.getInfo());
System.out.println(perC.getInfo());
}
}
通过执行结果可以发现,修改了一个对象的属性之后,所有对象对应的属性都发生了改变,所以这样的属性称为公共属性,公共属性必须通过static定义,而对于公共属性的内容保存不会在栈,也不会在堆,而是会存在于全局数据区之中,所有的方法保存在全局代码区之中。
既然static属于全局属性,那么由一个对象进行修改是否合适?很显然不合适,最好的做法就是利用类。所以对于static定义的属性可以由类名称直接进行调用,所以这样的属性也被称为类属性。
Person.country="中国-唐朝";//直接通过类来调用
此时类中存在有static属性以及非static属性,需要注意的是:
- 所有非static属性都是在对象实例化的时候才会进行内存分配;
- 所有的static属性在没有实例化对象产生的情况下直接使用。
范例:直接调用类属性
public class Hello {
public static void main(String args[]){
System.out.println(Person.country);
Person.country="北宋";
System.out.println(Person.country);
}
}
public class Hello {
public static void main(String args[]){
System.out.println(Person.country);
Person.country="北宋";
System.out.println(Person.country);
System.out.println(new Person("小机灵鬼",20).getInfo());
}
}
虽然static的属性定义在类中,但是它是完全独立的,不受实例化对象的控制。
在百分之九十的情况下类的设计都会用static属性,只有在表示公共的属性或与类实例化无关的属性时才会考虑使用static。
利用static定义方法
利用static定义的属性可以直接通过类名称进行访问,但是static也可以用于方法的定义上,同样,该方法可以由类名称直接调用。
范例:定义static方法
class Person{
private String name;
private int age;
private static String country = "中华人民共和国";//此属性暂时不封装
public Person(String name,int age){
this.name=name;
this.age=age;
}
public static void setContry(String c){
country=c;
}
public static String getCountry(){
return country;
}
public String getInfo(){
return "姓名:"+this.name+",年龄:"+this.age+",国家:"+this.country;
}
}
public class Hello {
public static void main(String args[]){
//此时没有实例化对象产生
System.out.println(Person.getCountry());
Person.setContry("清朝");
System.out.println(Person.getCountry());
System.out.println(new Person("小淘淘",20).getInfo());
}
}
static的方法依然不受到实例化对象的控制,所以可以由类名称直接调用。
但是此时类中的方法就存在有两种:static方法、非static方法,两种方法之间的互相访问就会出现问题:
- 所有的非static方法可以直接调用static方法或static属性;
- static方法不能够直接调用非static方法或非static属性;
分析?为什么会出现有这样的定义呢? - 所有的static属性或方法可以在类没有实例化对象的时候进行直接调用;
- 所有非static属性或方法必须在类产生实例化对象之后才可以进行调用。
那么什么时候可以用static方法呢? - 类设计的过程中百分之九十的方法都使用非static方法
- 如果一个类中没有任何的属性,那么这个类不需要定义普通方法,只需要定义static方法。
范例:对比一下两种代码
因为此时MyMath类没有属性,没有属性就不需要使用到堆内存,若使用第一种方式,则会开辟一块无用的堆内存空间。所以此时第二种方法更合理。
观察主方法(理解)
在最早讲解方法定义的时候给出了两种方案:
- 第一种:某一个方法定义在主类中,并且由主方法直接调用,定义格式:
public static 返回值类型 方法名称(){}
-第二种:某一方法定义在类中,并且有实例化对象进行调用,定义格式:
public 返回值类型 方法名称(){}
下面来做简单分析:
如果主类中定义的方法没有使用static,那么肯定无法通过主方法直接进行调用。此时只能够通过产生本类实例化对象的方式进行调用。
public class Hello {
public static void main(String args[]){
new Hello().print();
}
public void print(){
System.out.println("*****Hello!!!*****");
}
}
以后编程中,主类不会定义方法,方法大部分封装在类之中,通过产生对象进行调用。
Java中的主方法是历史上最长的:
- public:访问权限,所有操作者可见;
- static:执行一个类的时候输入:“java类名称”,表示由类直接调用;
- void:主方法是一切的起点,开始了就一直继续
- main:系统定义好的方法名称
- String args[]:程序执行时的输入参数,初始化参数。
范例:取得初始化输入参数
public class Hello {
public static void main(String args[]){
for(int x=0;x<args.length;x++){
System.out.println(args[x]);
}
}
}
输出为空。
如果要输入参数,则在解释Java程序时,类后面用空格设置,每个属性间用空格区分。
如果输入的参数本身就带有空格,那么这个时候可以使用“"”转义。
static应用
static在一些系统类库中会大量出现,那么这些就有可能是static方法导致的。static属性有一个最好的特点在于:公共属性,所有对象都可以对其进行修改。
范例:实现一个属性的个数统计
所有的新的对象产生时都一定要调用构造方法,所以可以在构造方法里增加一个统计。
class Person{
private static int count=1;//统计个数
public Person(){
System.out.println("对象个数:"+count++);
}
}
public class Hello {
public static void main(String args[]){
new Person();new Person();new Person();
}
}
进行修改,假设Person中存在一个name属性,那么在Person中提供两个构造方法:一个是负责接收name属性内容的,一个是无参的,无论适用哪种方法,都要求为name属性设置一个名字,而不是null。这种属性自动命名的操作就可以通过static属性实现。
范例:为属性自动命名
class Person{
private static int count=1;//统计个数
private String name;
public Person(){
this("无名氏——"+count++);
}
public Person(String name){
this.name=name;
}
public String getName(){
return this.name;
}
}
public class Hello {
public static void main(String args[]){
System.out.println(new Person().getName());
System.out.println(new Person().getName());
System.out.println(new Person("SMITH").getName());
}
}
这样的操作以后在高级部分会见到应用。