1. 为什么要使用静态变量、常量和方法
通常,在处理问题,会遇到多个不同的类要使用同一变量,常量或方法,然而,同一个常量在不同的类中创建时系统都会为之分配内存,造成内存浪费,如果能将这些不同类中的变量共享到一个内存中,那就大大减少了内存的使用,而静态变量(关键字 static)就是解决这个问题的。如下图所示:
2. 被声明的static的变量,常量和方法被称为静态成员,静态成员属于类所有,区别于个别对象,可以在本类或其他类使用类名“.”运算符调用静态成员。如下代码:
1 public class AnyThing {
2 static double PI = 3.1415; //在类中定义静态常量
3 static int id; //在类中定义静态变量
4 public static void method1(){ //在类中定义静态方法
5
6 }
7 public void method2(){
8 System.out.println(AnyThing.PI); //调用静态常量
9 System.out.println(AnyThing.id); //调用静态变量
10 AnyThing.method1(); //调用静态方法
11 }
12 }
注意:(1) 虽然静态成员可以使用“对象.静态成员”的形式进行调用,但通常不这么使用,这样容易混淆静态成员和非静态成员。
(2) 在静态方法中不可以使用this关键字。
(3) 在静态方法中不可以直接调用非静态方法。
(4) 在Java中规定不能将方法中的局部变量声明为static的。
(5) 如果在执行类时,希望先执行类的初始化动作,可以使用static定义一个静态区域,例如
1 public class example{
2 static{
3 ...
4 }
5 }
当这段代码被执行时,首先执行static块中的程序,并且只会执行一次,即在类加载的时候就被执行,之后执行main()方法。并且只是自上而下的顺序执行。
3.在java中,静态方法和普通方法的区别:
1、在外部调用静态方法时,可以使用"类名.方法名"的方式,也可以使用"对象名.方法名"的方式。而实例方法只有后面这种方式。也就是说,调用静态方法可以无需创建对象。 2、静态方法在访问本类的成员时,只允许访问静态成员(即静态成员变量和静态方法),而不允许访问实例成员变量和实例方法;实例方法则无此限制。 3、程序的static块只能调用静态方法,不能调用实例的方法。 如果要追溯其区别的根源,可以这样理解:在编译期间静态方法的行为就已经确定,而实例方法只有在运行期间当实例确定之后才能确定。
基本练习
package test_01;
public class static_class {
static int a =100;
int b=200; //实例变量
public static void main(String[] args) {
// TODO Auto-generated method stub
// static int a =100; //局部变量不能定义static
System.out.println("主函数");
static_fangfa();
//public_fangfa(); //也不能在静态函数中调用静态函数 ,除非把非静态函数变为静态函数
}
// 静态块
static {
System.out.println("静态块");
}
public static_class() {
// TODO Auto-generated constructor stub
System.out.println("构造方法");
}
private static void static_fangfa() {
System.out.println("静态函数");
static_class static_class1 =new static_class();
System.out.println(static_class1.a);
// System.out.println(static_class.b); // 静态函数里面不能调用静态变量
}
public void public_fangfa() {
int c = 100+b;
System.out.println("非静态函数"+c);
}
}
输出结果:
静态块 主函数 静态函数 构造方法 100
4.静态代码段
a. 静态代码块只能定义在类里面,它独立于任何方法,不能定义在方法里面
b.静态代码块里面的变量都是局部变量,只在本块内有效
c.静态代码块会在类被加载时自动执行,而无论加载者是JVM还是其他的类
d. 一个类中允许定义多个静态代码块,执行的顺序根据定义的顺序进行
e.静态代码块只能访问类的静态成员,而不允许访问实例成员
5.java中的初始化顺序
JAVA类首次装入时,会对静态成员变量或方法进行一次初始化,但方法不被调用是不会执行的,静态成员变量和静态初始化块级别相同,非静态成员变量和非静态初始化块级别相同。
初始化顺序:先初始化父类的静态代码--->初始化子类的静态代码-->
(创建实例时,如果不创建实例,则后面的不执行)初始化父类的非静态代码(变量定义等)--->初始化父类构造函数--->初始化子类非静态代码(变量定义等)--->初始化子类构造函数
类只有在使用New调用创建的时候才会被JAVA类装载器装入创建类实例时,首先按照父子继承关系进行初始化类实例创建时候,首先初始化块部分先执行,然后是构造方法;然后从本类继承的子类的初始化块执行,最后是子类的构造方法类消除时候,首先消除子类部分,再消除父类部分
- 静态变量: 在类内部中,方法的外部声明的对象而且加上static;
- 实例变量: 在类内部中,声明不需要加static;
- static 函数名() --> 可以通过 类名.函数名() 调用,也可以通过 类对象.函数名() 调用;
- 函数名() -->只能通过类对象.函数名() 调用;
6.Java静态对象和非静态对象的区别
静态对象 非静态对象
拥有属性: 是类共同拥有的 是类各对象独立拥有的
内存分配: 内存空间上是固定的 空间在各个附属类里面分配
分配顺序: 先分配静态对象的空间 继而再对非静态对象分配空间,也就是初始化顺序是先静态再非静态。
7.Java静态对象的特点
A,静态对象的数据在全局是唯一的,一改都改。如果你想要处理的东西是整个程序中唯一的,弄成静态是个好方法。非静态的东西你修改以后只是修改了他自己的数据,但是不会影响其他同类对象的数据。
B,引用方便。直接用类名.静态方法名 或者 类名.静态变量名就可引用并且直接可以修改其属性值,不用get和set方法。
C,保持数据的唯一性。此数据全局都是唯一的,修改他的任何一处地方,在程序所有使用到的地方都将会体现到这些数据的修改。有效减少多余的浪费。
D,static final用来修饰成员变量和成员方法,可简单理解为“全局常量”。对于变量,表示一旦给值就不可修改;对于方法,表示不可覆盖。
8.静态变量、静态方法和静态块
通常情况下,类成员必须通过它的类的对象访问,但是可以创建这样一个成员,它能够被它自己使用,而不必引用特定的实例。在成员的声明前面加上关键字static就能创建这样的成员。如果一个成员被声明为static,它就能够在它的类的任何对象创建之前被访问,而不必引用任何对象(跟类是否有static修饰无关)。
你可以将方法和变量都声明为static。static 成员的最常见的 例子是main( ) 。声明为static的方法有以下几条限制: ·
A,它们仅能调用其他的static 方法
B,它们只能访问static数据
C,它们不能以任何方式引用this 或super(this涉及到对象,super 与继承有关)
示例:Static 块仅在该类被加载时执行一次。下面的例子显示的类有一个static方法,一些static变量,以及一个static 初始化块。
public class TestNew {
static int a = 3;
static int b;
static void meth(int x){
System.out.println("x = "+x);
System.out.println("a = "+a);
System.out.println("b = "+b);
}
static {
System.out.println("static block initialized");
b = a*4;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
meth(42);
}
}
执行结果是:
static blockinitialized x = 42 a = 3 b = 12
上述classTestNew的执行顺序是:首先static 块执行(打印一条消息),a被设置为3,最后b被初始化为a*4 成12。然后调用main(),main () 调用meth() ,把值42传递给x。3个println ( ) 语句引用两个static变量a和b,以及局部变量x 。
9.外部使用静态变量或者静态方法
在定义它们的类的外面,static方法和变量能独立于任何对象而被使用,你只要在类的名字后面加点号运算符即可。可以看到,这种格式与通过对象引用变量调用非static方法或者变量的格式类似。示例:
class StaticDemo{
static int a = 42;
static int b = 99;
static void callme(){
System.out.println("a = "+a);
}
}
public class TestNew {
public static void main(String[] args) {
// TODO Auto-generated method stub
StaticDemo.callme();
System.out.println("b = "+StaticDemo.b);
}
}
执行结果:
a = 42 b = 99
10.静态内部类
静态内部类是指在一个类的内部,又定义了一个用static修饰的类。
A,首先,用内部类是因为内部类与所在外部类有一定的关系,往往只有该外部类调用此内部类。所以没有必要专门用一个Java文件存放这个类。
B,静态方法、静态成员变量。它唯一的作用就是随着类的加载(而不是随着对象的产生)而产生,以致可以用类名+静态成员名直接获得。这样静态内部类就可以理解了,它可以直接被用外部类名+内部类名获得。
public class Build {
..............
public static class VERSION {
................
public static final String RELEASE =getString("ro.build.version.release");
................
}
................
}
在外部可以直接通过Build.VERSION.RELEASE来访问。
11. 静态常量
静态常量不可变,可以直接被访问,如类名.静态常量名。例如:
public class MathTest{
public static final double PI= 3.1415926;
}
可以直接采用MathTest.PI的形式访问该PI常量。
13. 静态类与内部类的区别
内部类
1、内部类拥有普通类的所有特性,也拥有类成员变量的特性
2、内部类可以访问其外部类的成员变量,属性,方法,其它内部类
静态内部类
1、只有内部类才能声明为static,也可以说是静态内部类
2、只有静态内部类才能拥有静态成员,普通内部类只能定义普通成员
3、静态类跟静态方法一样,只能访问其外部类的静态成员
4、如果在外部类的静态方法中访问内部类,这时候只能访问静态内部类
/**
* 外部类,不能声明为 static
*
* @author zhanqi
*
*/
public class OuterClass {
private int ab = 1;
private static int sab = 2;
/**
* 普通内部类
*/
public class NormalInnerClass {
// private static int age = 22;
private int age = 22; // 不能声明为static
public NormalInnerClass() {
// 可以访问外部类静态与非静态成员
System.out.println(ab);
System.out.println(sab);
}
}
/**
* 静态内部类
*/
public static class StaticInnerClass {
// 定义静态与非静态成员都是可以的
private static int age = 22;
private int age2 = 22;
private void echo() {
// System.out.println(ab);
System.out.println(sab);// 只能访问外部类的静态成员
}
}
}
内部类实例化
1.访问内部类,必须使用:外部类.内部类,OutClass.InnerClass
2.普通内部类必须绑定在其外部类的实例上
3.静态内部类可以直接 new
/**
* 外部类访问内部类
*/
public class OuterClass {
/**
* 普通方法
*/
public void method() {
StaticInnerClass sic = new StaticInnerClass();
NormalInnerClass nic = new NormalInnerClass();
}
/**
* Main
*/
public static void main(String[] args) {
// 在静态方法中,只能访问静态成员,静态内部类
// NormalInnerClass nic = new NormalInnerClass();
StaticInnerClass sic = new StaticInnerClass();
}
}
/**
* 其它类访问内部类
*/
class Test {
public static void main(String[] args) {
/**
* 1:其它类访问内部类,必须使用:外部类.内部类,OutClass.InnerClass
* 2:普通内部类必须绑定在其外部类的实例上
* 3:静态内部类可以直接 new
*/
OuterClass.StaticInnerClass sic = new OuterClass.StaticInnerClass();
// OuterClass.NormalInnerClass n = new OuterClass.NormalInnerClass();
OuterClass oc = new OuterClass();
OuterClass.NormalInnerClass nic = oc.new NormalInnerClass();
}
}
静态对象
静态对象我们经常使用,但是对静态对象和非静态对象的区别却并不一定那么了解。下表格就是静态对象和非静态对象主要区别。
1.拥有的对象,静态对象是类共同拥有的 ,而非静态对象是由类单独拥有;
2.内存空间,静态对象内存空间是固定,非静态类对象是附着相关类的分配;
3.分配顺序,先分配静态对象的空间,然后才会分配非静态对象也就是初始化。