目录
? ? ? ??3.更改static则全变(所有对象共享static属性)
? ? ? ? 4.静态方法中不可以出现this和super
11.如果给静态方法加一个final,那么作用其实是标志着他不可以重写,本身就不可以重写,现在加上一个final就可以更好地区分了
????????成员属性叫成员变量叫实例变量 成员方法也叫实例方法 因为这两者都是基于对象的
? ? ? ? static直译是静态的,在java中作为一个修饰符可以用来修饰类,属性,方法,代码块
? ? ? ? 1.static的作用是使人知道修饰的东西是与类相关的,不用static修饰的是与对象相关的,
? ? ? ? 2.与类相关就理解成:由于所有的对象都是类实例化的结果,那么被static修饰的东西在所有的对象当中都是一样的内容
? ? ? ? 3.与对象相关就理解成,不同的对象的内容会随着对象的不同而变化
? ? ? ? 4.举个例子吧,人这个类有一个属性是染色体对数,不论是谁都有23对染色体(此处不考虑染色体异常),也就是说所有的对象都有一个值相同的属性,这个属性就可以设置为静态属性,表示只要这个类那么他的这个属性一定是同一个值。现在有另一个属性,名字,不同的人有不同的名字,它随着对象的变化而变化,那么这种就不可以设置为静态的
? ? ? ? 在“修饰符”的位置添加上static即可
? ? ? ? eg:static int age = 10;
? ? ? ? 类名.属性名或方法名
? ? ? ? 1.修饰属性叫静态属性
? ? ? ? 2.修饰方法叫静态方法
? ? ? ? 3.修饰代码块叫静态代码块
? ? ? ? 4.修饰类叫静态内部类
????????5.可以修饰接口中的方法(不可以和abstract共存因为static无法重写,abstract必须重写)
? ? ? ? ? ? ? ? 【访问权限修饰符】 static 数据类型 属性名 = 属性值;
? ? ? ? ? ? ? ? 类名.属性? ? ? ?对象名.属性
之所以可以使用对象访问是由于静态属性在编译的时候会自动按照类去访问这个属性,编译的时候他把对象替换成类了
public class Person{
public static int dna = 46;
public static int headNum = 1;
private String name ;
public Person(){
}
public Person(String name ){
this.name = name ;
}
public String getName(){
return name;
}
public void setName(String name ) {
this.name = name ;
}
}
public class Run {
public static void main(String[] args){
Person a = new Person("牛马1号");
Person b = new Person("牛马2号");
System.out.println(a.dna);
System.out.println(b.dna);
System.out.println(Person.dna);
}
}
? ? ? ? 运行结果:
46
46
46
? ? ? ? ? ? ? ? 如果通过一个对象更改了static属性的值,那么所有对象的这个属性的值都会变
public class Person{
public static int dna = 46;
public static int headNum = 1;
private String name ;
public Person(){
}
public Person(String name ){
this.name = name ;
}
public String getName(){
return name;
}
public void setName(String name ) {
this.name = name ;
}
}
public class Run {
public static void main(String[] args){
Person a = new Person("牛马1号");
Person b = new Person("牛马2号");
System.out.println(a.dna);
System.out.println(b.dna);
System.out.println(Person.dna);
a.dna = 23;
System.out.println(a.dna);
System.out.println(b.dna);
System.out.println(Person.dna);
Person.dna = 20;
System.out.println(a.dna);
System.out.println(b.dna);
System.out.println(Person.dna);
}
}
运行结果
46
46
46
23
23
23
20
20
20
原因:
方法和变量存储在栈区
对象和对象的属性存储在堆区
字节码文件存储在方法区
每一个对象在堆区都会开辟一块空间,所以与对象相关的属性,对于不同对象都各自独立互不相干 ,但是静态属性加载在方法区当中,且只开辟一个空间
所以static修饰的属性会在类加载的时候加载到方法区里面
? ? ? ? ? ? ? ? 1.一个引用没有指向任何一个对象,但是他仍然可以调用自身静态的东西,因为在加载类的时候就已经加载出来了静态的东西,此时有没有对象不影响运行
? ? ? ? ? ? ? ? 2.一个引用没有指向任何一个对象就不可以调用非静态的东西,因为非静态的东西是与对象相关的,没有对象我根本无法调用
????????????????
public class Person{
public static int dna = 46;
public static int headNum = 1;
private String name ;
public Person(){
}
public Person(String name ){
this.name = name ;
}
public String getName(){
return name;
}
public void setName(String name ) {
this.name = name ;
}
}
public class Run {
public static void main(String[] args){
Person a = null;
System.out.println(a.dna);
a.getName();
}
运行结果
20
Exception in thread "main" java.lang.NullPointerException: Cannot invoke "com.software.staticWay.Person.getName()" because "c" is null
?? ?at com.software.staticWay.Run.main(Run.java:25)
????????5.如何统计创建的对象的个数(利用静态属性和构造方法)
public class Student {
static int legs = 2;
static int stuCount= 0;
public Student() {
stuCount++;
}
}
public class Run {
public static void main(String[] args){
Student one = new Student();
Student two = new Student();
Student three = new Student();
System.out.println(Student.stuCount);
}
}
? ? ? ? ? ? ? ? 【访问权限修饰符】static 返回值 方法名(形参列表){方法体}
? ? ? ? ? ? ? ? 类名.方法名(形参列表)
? ? ? ? ? ? ? ?1.?由于静态属性需要封装,所以需要写getter和setter方法(访问静态属性必须是静态方法)? ? ? ? 这时原本getter,setter方法的this和super不能使用了,要改成类名.属性了
????????????????2.成员方法可以访问静态属性但是静态方法不可以访问成员属性,因为静态方法是静态的,在加载类的时候还没有对象,那么成员属性就无法访问,从某种意义上来讲成员属性成员方法都是和对象相关的
? ? ? ? ? ? ? ? 3.与类相关的方法可以定义成静态方法
? ? ? ? ? ? ? ? static{代码}
? ? ? ? ? ? ? ? static属性在一些情况下需要在一些逻辑的情况下才能赋初始值,而不是像之前那样赋初始值,所以此时需要静态代码块来执行一些操作给静态属性赋初始值
? ? ? ? ? ? ? ? 静态代码块在类加载的时候由JVM执行
public class Anmail {
private static String hobby = "eat";
static{
hobby ="asd";
System.out.println(hobby);
System.out.println("这是父类静态代码块");
}
public Anmail(){
System.out.println("创建父类对象");
}
{
System.out.println("这是是父类普通代码块");
}
}
public class Cat extends Anmail{
static{
System.out.println("这是子类静态代码块");
}
public Cat(){
System.out.println("创建了子类对象");
}
{
System.out.println("这是是子类普通代码块");
}
}
public class Run {
public static void main(String[] args){
//此处开始静态代码块的内容
System.out.println("此处开始静态代码块的内容");
//此处体现的是只加载一次静态的东西,因为我现在需要
Anmail anmail1 = new Anmail();
Anmail anmail2 = new Anmail();
}
}
运行结果:
这是父类静态代码块
这是是父类普通代码块
创建父类对象
这是是父类普通代码块
创建父类对象?
?由此可见执行顺序是:静态代码块——>普通代码块——>构造方法
? ? ? ? 而且静态代码块在一次程序的执行过程中只加载一次由上述内容可知,静态代码块只加载一次(只在第一次加载类的时候加载)(他是给类相关的属性(static属性)赋初值的),非静态的东西每创建一个对象加载一次
public class Anmail {
private static String hobby = "eat";
static{
hobby ="asd";
System.out.println(hobby);
System.out.println("这是父类静态代码块");
}
public Anmail(){
System.out.println("创建父类对象");
}
{
System.out.println("这是是父类普通代码块");
}
}
public class Cat extends Anmail{
static{
System.out.println("这是子类静态代码块");
}
public Cat(){
System.out.println("创建了子类对象");
}
{
System.out.println("这是是子类普通代码块");
}
}
public class Run {
public static void main(String[] args){
//此处开始静态代码块的内容
System.out.println("此处开始静态代码块的内容");
//此处体现父子类时的执行顺序
Cat cat1 = new Cat();
}
}
执行结果:
?这是父类静态代码块
这是子类静态代码块
这是是父类普通代码块
创建父类对象
这是是子类普通代码块
创建了子类对象
由此可见先加载静态代码块(先执行父类后执行子类),然后加载父类普通代码块然后加载父类构造方法然后加载子类普通代码块然后加载子类构造方法
总结:
先加载静态的,再加载对象(先加载父类普通代码块和构造方法,后加载子类普通代码快和构造方法)
如果有多项静态的东西,那么看定义顺序,定义顺序比较靠前,那么就先加载靠前的东西
????????重写基于多态,多态是作用在不同的对象上效果不同,强调对象,所以static不能重写
? ? ? ? 由此可知static修饰的方法不能重写
????????private static final 属性类型 属性名 = 属性值;
????????只能修饰成员内部类形成静态内部类,不可以修饰外部类
? ? ? ? 由于static修饰的方法不可以重写,所以static修饰的方法必须有方法体
? ? ? ? abstract定义的是抽象方法,不可以写方法体,所以abstract和static不共存