实例字段:在一个class中定义的字段。(使用new+构造方法来创建一个对象也就是创建一个实例)实例字段的特点是,每个实例都有独立的字段,各个实例的同名字段互不影响。
还有一种字段,是用static修饰的字段,称为静态字段:static field。
实例字段在每个实例中都有自己的一个“独立空间”,但静态字段只有一个“共享空间”,所有实例都会共享该字段。
import java.util.ArrayList;
//static field
public class Main {
public static void main(String[] args){
Person ming = new Person("xiaoming",12);
Person hong = new Person("XiaoHong",13);
ming.number = 18;
System.out.println(hong.number);//输出18
hong.number = 33;
System.out.println(ming.number);//输出33
//对于静态字段,无论修改哪个实例的静态字段,效果都是一样的:所有实例的静态字段都被修改了,原因是静态字段并不属于实例
}
}
class Person{
public String name;//类的属性
public int age;
public static int number;//定义静态字段number
public Person(String name,int age){//构造方法来初始化实例
this.name = name;
this.age = age;
}
}
虽然实例可以访问静态字段,但是它们指向的其实都是Person class的静态字段。所以,所有实例共享一个静态字段。
因此,不推荐用实例变量.静态字段去访问静态字段,因为在JAVA程序中,实例对象并没有静态字段。在代码中,实例对象能访问静态字段只是因为编译器可以根据实例类型自动转换为类名.静态字段来访问静态对象。
推荐用类名来访问静态字段,可以把静态字段理解为描述class本身的字段(非实例字段)
Person.number = 18;
静态方法
用static修饰的方法称为静态方法。调用静态方法用过类名就可以调用。
因为静态方法属于class而不属于实例,因此,静态方法内部,无法访问this变量,也无法访问实例字段,它只能访问静态字段。
通过实例变量也可以调用静态方法,但这只是编译器自动帮我们把实例改写成类名而已。
通常情况下,通过实例变量访问静态字段和静态方法,会得到一个编译警告。
静态方法经常用于工具类。例如:Array.sort()
静态方法也经常用于辅助方法。注意到Java程序的入口main()也是静态方法。
接口的静态字段
因为interface是一个纯抽象类,所以它不能定义实例字段。但是,interface是可以有静态字段的,并且静态字段必须为final类型
interface Person{
int MALE = 1;//编译器会自动加上public static final
int FEMALE = 2;
}
package helloworld;
//static method
//给Person类增加一个静态字段count和静态方法getCount,统计实例创建个数
public class Main {
public static void main(String[] args){
Person p1 = new Person("小明");
System.out.println(Person.getCount());//输出1
Person p2 = new Person("小红");
System.out.println(Person.getCount());//输出2
Person p3 = new Person("小军");
System.out.println(Person.getCount());//输出3
}
}
class Person {
String name;//类成员在不写修饰符的情况下,默认为default类型,default类型变量只能在同包中调用
private static int count = 0;//定义静态字段
public static int getCount(){//静态方法
return ++count;
}
public Person(String name){
this.name = name;
}
}
包
在Java虚拟机执行的时候,JVM只看完整类名,因此,只要包名不同,类就不同。注意:包可以是多层结构,并且包没有父子关系。
包作用域:位于同一个包的类,可以访问包作用域的字段和方法。不用public、protected、private修饰的字段和方法就是包作用域。
package helloworld;
public class Person{
//包作用域
void hello(){
System.out.println("Hello!");
}
}
public class Main {
public static void main(String[] args){
Person p = new Person();
p.hello();//同一个包,就可以调用Person()类的方法
}
}
作用域
public:定义为public的class、interface可以被其他任何类访问。
package helloworld;
public class Hello{
public void hi(){
}
}
上面的Hello是public,因此,可以被其他包的类访问
package abc;
class Main{
void foo(){
//Main可以访问Hello
Hello h = new Hello();
h.hi();//定义为public的field、method可以被其他类访问,前提是首先要能访问Hello类
}
}
private:定义为private的field、method无法被其他类访问。确切的说,private访问权限被限定在class的内部,而且与方法声明顺序无关。由于Java支持嵌套类,如果一个类内部还定义了嵌套类,那么,嵌套类拥有访问private的权限:
package helloworld;
//private
public class Main {
public static void main(String[] args){
}
//private方法
private static void hello(){
System.out.println("private hello!");
}
//定义在一个class内部的class称为嵌套类(nested class)
//静态内部类
static class Inner{
public void hi(){
Main.hello();//调用静态方法用类名可直接调用
}
}
}
protected:作用于继承关系。定义为protected的字段和方法可以被子类访问,以及子类的子类
public class Hello{
//protected方法
protected void hi(){
}
}
class Main extends Hello{
void foo(){
Hello h = new Hello();
h.hi();//上面的protected方法可以被继承的类Main()访问
}
}