0123 final关键字,static 关键字
1、final关键字
(1)final关键字修饰类,那么这个被修饰的类叫做太监类,不可以被继承,没有子类。
(2)final修饰方法,这个方法可以被继承但是不可以被重写,普通方法被重写后可以被final修饰
(3)final修饰变量:一次赋值终身不变
(4)final修饰成员变量(基本数据类型,引用数据类型):必须显示赋值,或者通过构造方法赋值
(5)final修饰局部变量(基本数据类型,引用数据类型):定义时可以不赋值,用的时候再赋值
创建一个爷爷类
public class Ye { public final void eat(){ System.out.println("爷爷吃饭"); } public void sleep(){ System.out.println("爷爷睡觉"); } }
创建一个父类
public final class Fu extends Ye { /*public void eat(){ }*/ public final void sleep() { // TODO Auto-generated method stub super.sleep(); } }
创建一个子类
//不可以继承final修饰的父类 public class Zi /*extends Fu*/{ // final int a=1; /*public Zi(int a){ this.a=a; }*/ }
注:Fu类是被final修饰的类,所以Zi类不可以继承Fu类。Fu类继承Ye类,不可以重写Ye类被final修饰的eat方法,重写Ye类中的sleep方法后可以再用final修饰。
在Zi类中定义的int a被final修饰,要么定义时显示赋值,要么通过构造方法进行赋值,如果通过构造方法赋值,则需要以后每一个构造方法都需要再写赋值语句。一次赋值终身不变
创建一个测试类,该测试类不依照上方的类测试
public class Demo01 { public static void main(String[] args) { final int a; a=2; final Person p=new Person("bbb",18); p.setName("aaa"); } }
在测试类中被final修饰的int a;定义时没有给赋值,用到的时候给a赋值了一个2。用final修饰引用数据类型时,创建对象可以直接赋值bbb,18,可以再将bbb改成aaa,原因是final修饰的引用数据类的地址值,地址值并没有发生改变,改变的是这个地址的属性,所以可以改动。
2、static关键字
被static修饰的成员变量属于类,不属于类的某个对象,也就是说,多个对象调用这个被static修饰的成员变量时,只要一个对象修改了这个成员变量的属性值,则所有调用这个成员变量的对象都发生了改变
例:创建一个Student类
public class Student { private String name; static String schoolname; public String getName() { return name; } public void setName(String name) { this.name = name; } public Student(String name) { super(); this.name = name; } public Student() { super(); } }
创建一个测试类
public class Demo01 { public static void main(String[] args) { Student s1=new Student("小红帽","清华大学"); Student s2=new Student("小兰帽","清华大学"); Student s3=new Student("小白帽","清华大学"); s3.schoolname="北京大学"; System.out.println(s1.getName()+"..."+Student.schoolname); System.out.println(s2.getName()+"..."+Student.schoolname); System.out.println(s3.getName()+"..."+Student.schoolname); } }
那么这个运行结果是
小红帽...北京大学
小兰帽...北京大学
小白帽...北京大学
图解:
那我们说被static修饰的成员变量属于类,类需要用public修饰,可以直接通过类名调用,上述中用对象调用是不合适的,
那更改一下代码、
创建一个苏student类 里写一个静态方法
public class Student { private String name; public static String schoolname; public String getName() { return name; } public void setName(String name) { this.name = name; } public Student(String name) { super(); this.name = name; } public Student() { super(); } public static void eat(){ System.out.println("这是静态方法"); } }
创建一个测试类
public class Demo01 { public static void main(String[] args) { Student s1=new Student("小红帽"); Student s2=new Student("小兰帽"); Student s3=new Student("小白帽"); Student.schoolname="北京大学"; System.out.println(s1.getName()+"..."+Student.schoolname); System.out.println(s2.getName()+"..."+Student.schoolname); System.out.println(s3.getName()+"..."+Student.schoolname); Student.eat(); } }
static 修饰方法,静态方法不能访问非静态方法,非静态方法可以访问静态方法
例:
非静态方法get2可以访问静态的方法get public static void get(){ System.out.println("静态方法"); } public void get2(){ get(); }
注意事项:静态内容优先于对象的存在,只能访问静态,不能使用this和super关键字。在同一个类中静态成员只能访问静态成员。
在多态种,所有的方法都是用的非静态方法和非静态成员变量,所以在调用成员变量时,编译运行都看左边,调用成员方法时,编译看左边,运行看右边
如果在多态中,全部使用的静态成员变量和静态成员方法,则无论是调用成员变量还是成员方法,都是编译运行看左边
例:创建一个Fu类
public class Fu { static int a=1; static int b=2; public static void eat(){ System.out.println("父类吃饭"); } public static void sleep(){ System.out.println("父类睡觉"); } }
创建一个子类继承Fu类
public class Zi extends Fu{ static int a=10; static int c=30; public static void eat(){ System.out.println("子类吃饭"); } public static void play(){ System.out.println("子类玩耍"); } }
创建一个测试类
public class Demo02 { public static void main(String[] args) { // TODO Auto-generated method stub Fu f=new Zi(); System.out.println(f.a); System.out.println(f.b); //System.out.println(f.c); f.eat(); f.sleep(); //f.play(); } }
运行结果
1
2
父类吃饭
父类睡觉
因为所有的成员变量和成员方法都用了static修饰,所以创建多态对象时,不能调用子类独有的变量和方法,编译运行时都以父类为基础(在这里不担心父类会有抽象方法,因为抽象方法abstract关键字与final关键字和static 关键字冲突,有static就不会有抽象方法)
定义静态常量
是用public static final 关键字修饰完成的
定义格式 public static final 数据类型 变量名 = 值;
当我们想使用类的静态成员,可以直接使用类名调用成员变量或者方法名
注:在接口中每个成员变量都是默认的用public static final 来修饰的,所有接口中的成员变量已经是静态形式,因为接口中没有构造方法,所以必须显示赋值,可以直接通过接口名进行访问