特点:
static 用于修饰成员(成员函数和成员函数)
static的存在,优先于对象存在,随着类的加载而加载
static所修饰的成员,被所有对象共享
static可以直接被类名调用,格式:System.out.println(Person.country);:类名.静态成员
使用细节
静态方法只能访问静态成员,即static修饰的成员,static int data;
静态方法不可以写this、super:this代表着当前调用该方法的对象。
主函数(main)是静态的 : public static void main(String[] args)
import java.util.Scanner;
import javax.naming.ldap.SortControl;
class Person
{
String name;//成员变量/实例变量
static String country = "CN";//静态变量/类变量
public void show ()
{
System.out.print(country+" : "+name);
}
}
public class Main
{
public static void main (String[] args)
{
Person BLF = new Person();
Scanner cin = new Scanner(System.in);
//BLF.name = cin.nextLine();
BLF.name = "BLF2";
BLF.show();
System.out.println(Person.country);//static 共享,可以直接用类名输出
//但是不可滥用,有些数据毕竟是特有的,不是共享的
//比如中国人 ,国籍是共享的,但是姓名是特有的
cin.close();
}
}
成员变量和静态变量的区别:
1.两者生命周期不同。静态的生命周期长
成员变量随着对象的创建而存在,随着对象的释放而释放,即成员变量的存在取决于对象的存在与否
静态变量随着类的加载而加载,随着类的消失而消失
2.调用方式不同
成员变量只能被对象调用
静态变量可以被对象调用,可以用类名调用,所以有static修饰的成员,最好用类名调用,清晰,且不用创建对象
3.
成员变量称为实例变量
静态变量称为类变量
4.两者存储位置不同
成员变量存储在堆内存的对象中,所以也叫对象的特有数据(堆里不肯能放变量,只能放实体,实体里可以有变量)
静态变量的数据存储在方法区(数据区/共享区)中的静态区,所以也叫对象的共享数据
static在使用过程中的细节:
1.访问有局限性:static修饰的方法只能访问static修饰的成员
错误代码:
import java.util.Scanner;
import javax.naming.ldap.SortControl;
class Person
{
String name;
static String country = "CN";
public static void show ()
{
System.out.print(country+" : "+name);//因为有没有static修饰的成员name
//System.out.print(country+");//所以不能有name
}
}
public class Main
{
static int data = 9;
public static void main (String[] args)
{
Person BLF = new Person();
Scanner cin = new Scanner(System.in);
//BLF.name = cin.nextLine();
BLF.name = "hello";
BLF.show();
cin.close();
}
}
所以,static修饰的成员可以不用对象,直接用类名调用,因为对象还不存在,所以name自然也就不存在
(非静态既可以访问静态,又可以访问非静态)
public class Main
{
static int data = 9;//静态修饰成员变量
public static void main (String[] args)
{
show();
}
public void show() //此处如果想要调用,必须用静态修饰方法,data不加静态,叫做特有数据
//public static void show()//此方式可以访问static修饰的data
{
System.out.println(data);
}
}
想访问特有数据data,所以想要调用一个show方法,可以用对象调用
public class Main
{
int data = 9;//静态修饰成员变量
public static void main (String[] args)
{
Main BLF = new Main();
BLF.show();
}
public void show()
{
System.out.println(data);
//也可以System.out.println(Main.data);//Main. 可以省略
}
}
故,主函数用来指挥其他对象工作,把代码封装到函数中,再把函数封装到每个类中,main只需要创建那么对象,指挥那么对象工作即可
主函数main解析:
1:格式是固定的
2.被jvm识别和使用
public因为权限最大
static不需要对象,直接用主函数main所属类名调用即可
void没有返回值
main:不是关键字,被jvm识别的一个固定名字
String[] args:是main函数的一个参数列表,是一个数组类型的参数,且参数是字符型的
import java.util.Scanner;
public class Main
{
public static void main (String[] args)
{
Scanner cin = new Scanner(System.in);
System.out.println(args);// 打印 [Ljava.lang.String;@7d4991ad
}
}
有地址,则证明有实体,其长度:
import java.util.Scanner;
public class Main
{
public static void main (String[] args) //=> new String[0]
{
Scanner cin = new Scanner(System.in);
System.out.println(args.length);// 打印 0
}
}
产生了一个数组实体,但是并未存东西,在java运行程序时:可以传具体的参数值,可以在程序入口,可以传你需要的参数,无论传什么都是字符串,字符串可以转化为其他类型。
当然:args是唯一可变化的,想怎么写怎么写,但是已经形成了一种习惯了,早期是arguments:参数
import java.util.Scanner;
public class Main
{
public static void main (String[] args)
{
Scanner cin = new Scanner(System.in);
for(int i = 0;i<args.length;i++)
{
System.out.println(args[i]);
}
System.out.println(args.length);
}
}
运行图如下:
当然了,可以写成这种格式:
import java.util.Scanner;
public class Main
{
public static void main (String[] args) //程序入口
{
Scanner cin = new Scanner(System.in);
int x = 10;
main(x);
}
public static void main(int x)//重载嘛
{
System.out.println(x);
}
}
内存加载示意图:
static什么时候用?
static修饰符,只能修饰成员(成员变量和成员函数)
1.静态成员变量
不加static是在对象里,对象特有,加了static是方法区里,对象共享
对象在堆内存,当多个对象中所具备的同一个成员变量的值都是相同的,那么就没必要每个对象都存一份,
那么这个成员值就可以抽离出来,就可以用static修饰(为了空间的有效利用),但是如果有一个对象的该
变量的值不一样,那么就是对象的特有值,就不能用static修饰,非静态。
2.静态函数
函数是否加static修饰(也就是函数是可以被类直接调用还是被对象直接调用),关键看这个函数里是否存在对象的特有数据也就是该函数是否需要访问非静态的成员变量,如果需要就可以定义为非静态的。如果不需要就可以定义为静态的,当然也可以是非静态的,但是如果方法没有访问特有数据,就没必要建立对象,建立对象反而在浪费内存,直接用类名调用即可
错误代码演示:访问静态变量
import java.util.Scanner;
class MAN
{
static int num = 5;
int age;
public void show()//未加静态//所以要加public static void show()
{
System.out.println(num);
}
}
public class Main
{
public static void main (String[] args)
{
MAN.show();//报错
}
}
访问特有数据,就必须有对象
import java.util.Scanner;
class MAN
{
static int num = 5;
int age;
public void show()//未加静态
{
System.out.println(age);
}
}
public class Main
{
public static void main (String[] args)
{
MAN.show();//报错
new MAN.show();
}
}
随着类的加载而执行,而且只执行一次,也就是第一次引用类的时候
作用:静态代码块用于给类初始化(构造函数是给对象初始化)
import java.util.Scanner;
class MAN
{
static
{
System.out.println("BLF");
}
void show()
{
System.out.println("BLF2");
}
}
1.public class Main
{
public static void main (String[] args)
{
new MAN().show();
}
}
//BLF
//BLF2
2.public class Main
{
public static void main (String[] args)
{
new MAN().show();
new MAN().show();
}
}
//BLF
//BLF2
//BLF2 类已经存在了
静态代码块对类赋初值
class MAN
{
static int num ;
static
{
num = 9;
num *=2;
}
static void show()
{
System.out.println(num);
}
}
public class Main
{
public static void main (String[] args)
{
MAN.show();
MAN jo = new MAN();
jo.show();
}
}
<strong><span style="font-size:18px;">静态代码块应用不多,一般这个类都是静态的,会使用静态代码块</span></strong>
public class Main
{
static
{
System.out.println("a");
}
public static void main (String[] args)
{
System.out.println("b");
}
}
<span style="font-size:18px;"><strong>打印a
b
主函数被调用才会执行</strong></span>
注意一般情况下,static是不能修饰类的,如果一定要用static修饰类的话,通常static修饰的是匿名内部类。
在一个类中创建另外一个类,叫做成员内部类。这个成员内部类可以静态的(利用static关键字修饰),也可以是非静态的。