static(静态)
- 静态成员属于类本身的,而不是属于对象,被类的所有对象所共有。
- 即便不创建对象,也可以使用类本身的静态成员。
- 静态成员分为
- 静态数据成员。
- 静态方法成员。
- 使用静态成员的两种方法
- 类名.静态成员名
- 类对象名.静态成员名
static方法
- 在静态方法里只能调用同类中其它的静态成员(包括变量和方法),而不能直接访问类中的非静态成员。
- 静态方法能以任何形式引用this和super关键字。
- 静态方法只能访问类的静态成员。但非静态方法可以访问类中所有成员,包括静态成员。
如果在一个属性前面加了static之后,这个属性就不属于某个对象的了,属于n个对象
共用的同一个属性。
当一个成员被加了static之后,它就已经被存放到了data segment区域,不需要实例化就能访问它。
例子:A类的多个对象共用一个static属性i。
class A
{
public int i=10;
public void show()
{
System.out.printf("i=%d\n",i);
}
}
public class Test1
{
public static void main(String[] args)
{
A aa1 = new A();
//这个对象aa1在heap区域分配了一块内存,存储i;
A aa2 = new A();
//这个对象aa2在heap区域分配了一块内存,存储i;
aa1.i = 20;
aa2.show();//i=10 //aa2对象调用show方法,则show方法显示的是aa2中的i的值。
//创建的两个对象中的i互不影响。这个容易理解
}
}
—对比下一个程序—
class A
{
public static int i=10; //这个变量前面加了static关键字
public void show()
{
System.out.printf("i=%d\n",i);
}
}
public class Test1
{
public static void main(String[] args)
{
A aa1 = new A();
A aa2 = new A();
A aa3 = new A();
aa1.i = 20;
aa2.show();//这时的i=20;
//这说明了aa1的i和aa2的i是同一个i
System.out.printf("i=%d\n",aa3.i);//aa3.i还是等于20;。
//证明了aa1,aa2,aa3共用一个i。
//当系统给aa1分配空间的时候,已经不需要给i分配空间.
//i的空间已经被分配到 data segment(静态变量,字符串常量)区域了。
//证明了当某个属性前面被加了static之后,它就已经被分配到了data segment(静态变量,字符串常量)区域。
//而创建对象的时候,不再给它分配内存空间。
}
}
静态属性,是属于对象,还是属于类?
例子:
class A
{
public int i = 10;
}
public class Test1
{
public static void main(String args[])
{
System.out.printf("i=%d\n",A.i);
//这样写毫无疑问是不行的。
//在对象的时候就学过,类只是个模型,不是具体存在的。只有对象是具体存在的。
//所以在没有创建对象的情况下,无法访问i。
//会报错,无法从静态上下文中引用非静态变量i。
//证明了无法从静态上下文中引用非静态成员。
}
}
—如果给i加上static—
class A
{
public static int i = 10;
}
public class Test1
{
public static void main(String args[])
{
System.out.printf("i=%d\n",A.i);
// i=10;
//可以直接从类中访问变量。
}
}
本程序证明了:static属性i是属于类本身。
或者说:没有对象,我们仍然可以直接通过类名的方式访问该类内部的static属性。
可以类推出,不仅是变量,方法前面也可以加static,然后直接通过类名访问。
例子可以看上面的“函数的重载”笔记。
static属性的成员不仅可以通过类名访问,也可以跟没有static属性的成员一样可以通过对象名来访问。
class A
{
public static int i = 10;
public static void f()
{
System.out.printf("这是个静态方法\n");
}
}
public class Test1
{
public static void main(String agrs[])
{
A aa = new A();
A.f();//这样可以直接通过类名调用方法。
aa.f();//那么是否还能够通过对象名访问静态属性?
// 答案是可以的。
System.out.printf("i=%d\n",aa.i);//i=0;
}
}
证明了 static属性和方法虽然属于类本身,虽然可以通过类名的方式访问。
但是static属性和方法很明显也属于类对象,当然也可以通过类对象名访问。
如果要访问的静态成员在同一个类中,就可以直接访问,不需要通过对象名访问。
static与访问修饰符
- 只有非private的static成员才可以通过类名的方式访问。
- static只是表明了该成员具有了可以通过类名访问的潜在特征。但是否可以通过类名访问,还必须满足一个条件:该成员必须是非private。
class A
{
private static int i = 10;
protected static int j =20;
private static void f()
{
System.out.printf("这是个静态方法\n");
}
}
public class Test1
{
public static void main(String agrs[])
{
A aa = new A();
A.f();//error 不能通过类名访问私有的静态的类成员
aa.f();//error 不能通过对象名访问私有的静态的类成员
System.out.printf("i=%d\n",aa.i);
//error 不能通过对象名访问私有的静态的类成员
System.out.printf("j=%d\n",aa.j);//j=20;
//不会报错,能够输出aa.j的值
}
}
非静态方法是否可以访问静态成员?这个其实可以推理出来。
class A
{
private static int i = 10;//静态属性
public static void f()//静态方法
{
System.out.printf("FFFF\n");
}
public void g()//非静态方法
{
f();//调用同类的静态方法
System.out.printf("GGGG\n");
System.out.printf("i=%d",i);//访问静态属性
}
}
public class Test1
{
public static void main(String[] args)
{
A aa = new A();
aa.g();
//FFFF
//GGGG
//i=10
//说明了非静态方法能够访问静态成员。
//其实,要调用一个非静态方法就一定会创建一个对象。
//既然有了一个对象,那么就像上面说的。static也属于类对象。
//可以通过对象名访问,但是他们在同一个类里面,所以就省略了对象名。
}
}
非静态方法访问其他类中的静态成员
class A
{
public static int i = 10;//静态属性
public static void f()//静态方法
{
System.out.printf("FFFF\n");
}
}
class B //通过类名直接访问
{
public void h()
{
A.f();//可以访问
System.out.printf("i=%d",A.i);//可以访问
}
}
public class Test1
{
public static void main(String[] args)
{
B bb = new B();
bb.h();
//FFFF
//i=10
//证明了非静态方法能够访问不同类的静态成员
}
}
总结:
非静态方法可以访问静态成员。
静态方法可以访问静态成员。
静态方法不能访问非静态成员。
非静态方法是否能访问非静态成员,要看被访问的非静态成员是否创建了对象。有对象就能访问。
//这段话有点绕