Static关键字:可以用于修饰属性,也可以用于修饰方法,还可以用于修饰类。
Static修饰属性:无论一个类生产多少个对象,所有这些对象共同使用唯一一份静态的成员变量;一个对象对该成员变量进行了修改,其他对象的该静态成员变量的值也会随之发生变化。如果一个成员变量是static的,那么我们通过类名.成员变量名的方式来使用它(推荐使用这种方式)。
public class StaticTest{
public static void main(String args[]){
/*
MyStatic myStatic = new MyStatic();
MyStatic myStatic2 = new MyStatic();
myStatic.a = 10;
System.out.println(myStatic2.a);
*/
//使用类名访问成员变量
MyStatic.a = 10;
System.out.println(MyStatic.a);
}
}
class MyStatic{
static int a;
}
在程序中使用static声明属性,则此属性称为全局属性(或成为静态属性).
例1:使用static声明属性
class Person{
String name;
int age;
static String country = "A城"; //使用static申明类属性
public Person(String name, int age){
this.name = name;
this.age = age;
}
public void info(){
System.out.println("姓名:" + this.name + " 年龄:"
+ this.age + " 城市:" + this.country);
}
};
public class StaticDemo02{
public static void main(String args[]){
Person p1 = new Person("张三", 30);
Person p2 = new Person("李四", 30);
Person p3 = new Person("王五", 30);
System.out.println("------------修改之前---------");
p1.info();
p2.info();
p3.info();
System.out.println("------------修改之前---------");
Person.country = "B城"; //直接修改static属性
p1.info();
p2.info();
p3.info();
fun();
}
public static void fun(){
System.out.println("静态方法无法调用非静态方法,必须有static关键字");
};
}
static修饰方法:static 修饰的方法叫做静态方法。对于静态方法来说,可以使用类名.方法名 的方式来访问。
public class StaticTest2{
public static void main(String args[]){
//MyStatic2 test = new MyStatic2();
//test.output();
MyStatic2.output();
}
}
class MyStatic2{
public static void output(){
System.out.println("output");
}
}
//静态方法的继承
public class StaticTest3{
public static void main(String args[]){
M m = new N(); //结果取决于调用着的类型
//M m = new M();
m.output();
}
}
class M{
public static void output(){
System.out.println("M");
}
}
class N extends M{
public static void output(){
System.out.println("N");
}
}
//N类中的方法继承了M中的方法。并隐藏了M中的方法
参考文献:http://docs.oracle.com/javase/tutorial/java/IandI/override.html
例2:使用static声明方法。使用static声明的方法有时也成为类方法
class Person{
private String name;
private int age;
static String country = "A城"; //使用static申明类属性
public Person(String name, int age){
this.name = name;
this.age = age;
}
public void info(){
System.out.println("姓名:" + this.name + " 年龄:"
+ this.age + " 城市:" + this.country);
}
public static void setCountry(String c){ //使用static申明方法
country = c; //修改static属性
}
public static String getCountry(){
return country;
}
};
public class StaticDemo03{
public static void main(String args[]){
Person p1 = new Person("张三", 30);
Person p2 = new Person("李四", 30);
Person p3 = new Person("王五", 30);
System.out.println("------------修改之前---------");
p1.info();
p2.info();
p3.info();
System.out.println("------------修改之前---------");
Person.setCountry("B城"); //因为是使用static声明的方法,所以也可称为类方法
p1.info();
p2.info();
p3.info();
}
}
总结:
1. static声明的方法是不能调用非static类型声明的属性或方法(因为static得方法在装载class得时候首先完成,比 构造方法早,此时非static得属性和方法还没有完成初始化。。。所以不能调用)。但是非static声明的方法可以去调用static调用的属性或方法。
2. 使用 static 声明的属性或方法可以直接由类名称调用。
3. 只能访问 static 声明的属性或方法,而非 static 声明的属性和方法是不能访问,因为 static 可以在对象没有实例化时就直接调用,而其他的属性或方法必须在对象实例化之后才可以调用。
final关键字:final可以修饰 类、 方法、属性。
final修饰类:当一个类被 final 所修饰时,表示该类是一个终态类,即不能被继承。
public class FinalTest{
public static void main(String args[]){
}
}
final class E{ //该类不能被继承
}
class F extends E{
}
final修饰方法:当一个方法被 final 所修饰时,表示改方法时一个终态方法,即不能被重写(override)。
public class FinalTest2{
public static void main(String args[]){
H h = new H();
h.output();
}
}
class G{
public final void output(){
System.out.println("G");
}
}
class H extends G{
public void output(){
System.out.println("H");
}
}
final 修饰属性:当一个属性被final 所修饰时,表示该属性不能被改写。
public class FinalTest3{
public static void main(String args[]){
People people = new People();
people.age = 20;
}
}
class People{
final int age = 10;
}
//使用final修饰地址:
public class FinalTest3{
public static void main(String args[]){
People people = new People();
//people.address = new Address(); //Error,将新的地址赋值给address引用
people.address.name = "shanghai"; //修改的是address所指向的地址的内容
}
}
class People{
final Address address = new Address(); //将引用类型声明为final,意思是new出来的地址是不能改变的
}
class Address{
String name = "bejing";
}
总结:当final 修饰一个原生数据类型时,表示该原生数据类型的值不能发生变化(比如说不能从8变为20);如果final修饰的是一个引用数据类型时,表示该引用类型不能再指向其他对象了,但该引用所指向的对象的内容是可以发生变化的。
//final 陷阱
public class FinalTest4{
final int a; //必须显示的给变量赋值,否则报错。或者通过构造方法赋初值
public FinalTest4(){
a = 0;
}
public FinalTest4(int a){ //Error,因为有2个构造方法,调用时不知道会先调用哪个构造方法
//this.a = a;<span style="white-space:pre"> </span>//或者这样也可以
}
}
final陷阱:对于final 类型成员变量,一般来说有两种赋初值方式:
a) 在声明 final 类型成员变量时就赋上初值
b) 在声明 final 类型成员变量时不赋初值,但在类的所有构造方法中都为其赋上初值
·static 代码块: 静态代码块。静态代码块的作用也是完成一些初始化的工作。首先执行静态代码块,然后执行构造方法。静态代码块在类被加载的时候执行,而构造方法是在生成对象的时候执行;要想调用某个类生成对象,首先需要将类加载到 java 虚拟机上(JVM),然后由JVM 加载这个类生产对象。
//静态代码块
public class StaticTest4{
public static void main(String args[]){
/*
P p = new P();
P p2 = new P(); //static只执行一次,因为class只需要加载一次到JVM,然后每次new的时候执行构造方法。
*/
new S(); //因为静态代码块在加载到JVM的时候就执行了,所以先执行3个static方法,然后在依次查找子类上面的父类构造方法,从父类到一类依次执行。
new S();
}
}
class P{
static{
System.out.println("P static block"); //当将class文件加载到JVM时执行
}
public P(){
System.out.println("P constructor"); //当 new 这个类生产对象的时候执行
}
}
class Q extends P{
static{
System.out.println("Q static block");
}
public Q(){
System.out.println("Q constructor");
}
}
class S extends Q{
static{
System.out.println("S static block");
}
public S(){
System.out.println("S constructor");
}
}
·类的静态代码块只会执行一次,是在类被加载的时候执行的,因为每个类只会被加载一次,所以静态代码块也只会被执行一次;而构造方法则不然,每次生成一个对象的时候都会调用类的构造方法,所以 new 一次就会调用构造方法一次。
·如果继承体系中既有构造方法,又有静态代码块,那么首先执行最顶层的类的静态代码块,一直执行到最底层的静态代码块,然后在去执行最顶层类的构造方法,一直执行到最底层类的构造方法。 注意:静态代码块只会执行一次。
//静态方法调用
public class StaticTest5{
public static void main(String args[]){
W w = new W();
w.change();
}
}
class W{
static int a = 10;
int a = 10; //不能在一个静态方法里面访问一个非静态的成员变量
public static void change(){
//public void change(){ //可以因为a的值只有一份是全局的
a++;
this.a++;<span style="white-space:pre"> </span>//Error:this表示当前对象的引用。如果直接使用类名调用静态方法的时候,就不存在对象,也就不知道this是什么了
}
}
//因为每次new一个对象的时候都会有自己的一份a的值,所以在静态方法不知道是修改了哪个a的值。
·不能在静态方法中访问非静态成员变量;可以在静态方法中访问静态的成员变量。可以在非静态方法中访问静态的成员变量。
总结:静态的只能访问静态的;非静态的可以访问一切。
·不能在静态方法中使用 this 关键字。
java中的内存区域:
· 栈内存:可以保存对象的名称
· 堆内存:保存每个对象的具体属性
· 全局数据区:保存 static 类型的属性
· 全局代码区:保存所有方法的定义
main方法:
· public: 表示此方法可以被外部所调用
· static: 表示此方法可以由类名直接调用(执行一个java程序的时候,使用的是 java 类名称)
· void: 主方法是程序的起点,所以不需要任何的返回值
· mian: 系统规定好的默认调用的方法名称,执行的时候,默认找到main方法名称
· String args[]: 表示的是运行时的参数
· 参数传递的形式: java 类名称 参数1 参数2 参数3...
代码块:
概念:代码块是指用{}括起来的一段代码,根据位置不同可以分为 普通代码块、构造快、静态代码块、同步代码块 4种。
class Demo{
{ //定义构造快
System.out.println("1、构造块。");
}
static{ //定义静态代码块
System.out.println("0、静态代码块。");
}
{ //定义构造方法
System.out.println("2、构造方法。");
}
}
public class CodeDemo03{
static{ //在主方法所在的类中定义静态块
System.out.println("在主方法所在的类中定义静态块");
}
public static void main(String args[]){
new Demo();
new Demo();
new Demo();
}
}
//执行顺序:静态代码块优先于主方法执行,而在类中定义的静态代
//码块会优先于构造块执行,而且静态代码块只执行一次。