static修饰符
stati修饰符可用来修饰成员变量、成员方法和代码块
static变量
类的成员变量分两种:
类变量或静态变量:被static修饰的变量
实例变量:没有被static修饰的变量。
静态变量和实例变量的区别:
静态变量在内存中只有一个拷贝,运行java虚拟机只为静态变量分配一次内存,在加载类的过程中完成静态变量的内存分配,可以直接通过类名访问静态变量
实例变量,每创建一个实例,就会为实例变量分配一次内存。
public class Sample { public static int number; public void method() { int x = number; //在类中直接访问静态变量 }}public class Sample2 { public void method() { int x = Sample.number; //在其他类中通过类名访问静态变量。 }}
静态变量的两个作用
能被类的所有实例共享,可作为实例之间进行交流的共享数据。
public class Sample { public static int i; public void method() { i = 123; //该方法不用return即可将i值传递出去 } public static void main(String[] args) { Sample s = new Sample(); s.method(); System.out.println("i="+i); //打印 i=123 }}
如果类的所有实例都包含一个相同的常量属性,可把该属性定义为静态常量类型。
static final double PI=3.14;static int MAX_INPUT_VALUE=220;
用于统计次数
private static int count; //投票次数private static final int MAX_COUNT=100;//静态变量,最大投票数
import java.util.HashSet;import java.util.Set;public class Voter { private static int MAX_COUNT=100; //最大投票数 private static int count; //投票数 private static Setvoters = new HashSet ();//存放所有已经投票的选民 private String name; public Voter(String name) { //遍历voters集合 this.name = name; } //投票 public void voteFor() { if(count==MAX_COUNT){ System.out.println("投票活动已结束"); return; } if(voters.contains(this)) { System.out.println(name+":你不允许重复投票!"); }else { count ++; voters.add(this); System.out.println(name+":感谢您投票!"); } } //打印投票结果 public static void printVoteResult() { System.out.println("当前投票数为:"+count); System.out.println("参与投票的选民名单如下:"); for(Voter voter : voters) { System.out.println(voter.name); } } public static void main(String[] args) { Voter tom = new Voter("Tom"); Voter mike = new Voter("Mike"); tom.voteFor(); mike.voteFor(); Voter.printVoteResult(); }}
static 方法
成员方法分类静态方法(类方法)和实例方法
静态方法不需要创建类的实例,可以直接通过类名来访问
public class Sample { public static int add(int x,int y) { return x+y; }}public class Sample2 { public void method() { int result = Sample.add(1,2); System.out.println("result:"+result); }}
1、静态方法可访问的内容
静态方法中不能使用this和super关键字,也不能直接访问所属类的实例变量和实例方法。但可以访问所属类的静态变量和静态方法。
public class Base { protected int var1; //var实例变量 protected static int var2; public void method1() { var1++; } public static void method2() { var2++; } }public class Sub extends Base { public static void method2() { super.method(); //编译出错,静态方法中不能用super关键字。 ..... }}
2、实例方法可以访问的内容
实例方法克制直接访问所属类的静态变量、静态方法、实例变量和实例方法。
class Sample { protected int var1; protected static int var2; //实例方法 public void method1() { var1++; //直接访问实例成员 var2++; //直接访问静态成员 method2(); //直接访问静态方法 } //静态方法 public static void method2() { //var1++; //编译错误,静态方法中不能直接访问实例变量 var2++; //method1(); //编译错误,静态方法中不能直接访问实例方法 }}
总结:实例方法可以直接访问所属类的静态成员、静态方法、实例变量和实例方法。但静态方法只能访问所属类的静态成员和静态方法。
3、静态方法必须被实现
静态方法用来表示某个类的所特有的功能,这种功能的实现不依赖于类的具体实例,也不依赖于它的子类。故当前类必须为静态方法提供实现。
一个静态方法不能被定义为抽象方法。
4、作为程序入口的main()方法是静态方法
在main()静态方法中不能直接访问类的实例变量和实例方法。
public class Sample { int var; public void method() {...} public static void main(String[] args) { Sample s = new Sample(); //只能通过类的实例的引用来访问实例变量和实例方法 s.var = 1; s.method(); } }
5、方法的字节码都位于方法区
static代码块
static代码块在类加载时执行,优于main方法、优于其他方法执行。且只会被执行一次。
若有多个代码块,则按顺序依次执行。
public class Sample { static { System.out.println("代码块1"); } static { System.out.println("代码块2"); } public static void main(String[] args) { System.out.println("main方法") }}
类的构造方法用于初始化类的实例,而类的静态代码块则可用于初始化类,给类的静态变量赋初始值。