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");
}
}
执行结果:
D:\src>java StaticTest2
output
1. static 修饰方法:static 修饰的方法叫做静态方法。对于静态方法来说,可以使用类名.方法名的方式来访问。
2. 静态方法只能继承,不能重写(Override)。这个时候是隐藏了父类的静态方法,没有发生重写。同时静态方法不能覆盖非静态的方法,非静态的方法不能覆盖静态方法。【注意:这种需求一般在实际开发工程中不存在,可能在面试题目中会出现】
没有static关键字
public class StaticTest3{
public static void main(String[] args){
M m = new N();
m.output();
}
}
class M{
public void output(){
System.out.println("M");
}
}
class N extends M{
public void output(){
System.out.println("N");
}
}
执行结果:
D:\src>java StaticTest3
N
有static关键字
public class StaticTest3{
public static void main(String[] args){
M m = new N();
m.output();
}
}
class M{
public static void output(){
System.out.println("M");
}
}
class N extends M{
public static void output(){
System.out.println("N");
}
}
执行结果:D:\src>java StaticTest3
M
【说明】:这个时候是隐藏了父类的静态方法,没有发生重写,具体调用那个方法取决于m的类型,这个程序m的类型是M所以执行父类当中的方法.如果对以下程序 n的类型是N,所以执行N类中的静态方法。
例如修改上个程序第二行代码段
public static void main(String[] args){
N n = new N();
n.output();
}
则执行结果为:
D:\src>java StaticTest3
N
下面这个程序是为了验证静态方法是不能被重写的,用注释@Override来写,编译程序报错。
public class StaticTest3{
public static void main(String[] args){
M m = new N();
m.output();
}
}
class M{
public static void output(){
System.out.println("M");
}
}
class N extends M{
@Override
public static void output(){
System.out.println("N");
}
}
编译结果:
D:\src>javac StaticTest3.java
StaticTest3.java:15: 错误: 方法不会覆盖或实现超类型的方法
@Override
^
1 个错误
【说明】:注释@Override是为了告诉编译器我要对这个方法进行重写,而静态方法是不能被重写的显然报错。
3. final关键字:final可以修饰属性、方法、类。用fianl之后就不能去动它了简单讲就是这样。
4. final修饰类:当一个类被final所修饰时,表示该类是一个终态类,即不能被继承。
public class FinalTest{
public static void main(String[] args){
}
}
final class E{
}
class F extends E{
}
编译结果:
D:\src>javac FinalTest.java
FinalTest.java:9: 错误: 无法从最终E进行继承
class F extends E{
^
1 个错误
5. 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");
}
}
执行结果:
D:\src>javac FinalTest2.java
FinalTest2.java:15: 错误: H中的output()无法覆盖G中的output()
public void output(){
^
被覆盖的方法为final
1 个错误
6. final修饰属性:当一个属性被final所修饰时,表示该属性不能被改写。
public class FinalTest3{
public static void main(String[] args){
People people = new People();
people.age = 20;
}
}
class People{
final int age = 10;
}
执行结果:
D:\src>javac FinalTest3.java
FinalTest3.java:4: 错误: 无法为最终变量age分配值
people.age = 20;
^
1 个错误
【说明】:当age用final来修饰的时候,此时age不能再变化了,相当于age是一个常量了。
继续修改程序
public class FinalTest3{
public static void main(String[] args){
People people = new People();
// people.age = 20;
people.address = new Address();
}
}
class People{
//final int age = 10;
final Address address = new Address();
}
class Address{
String name = "Beijing";
}
编译结果:
D:\src>javac FinalTest3.java
FinalTest3.java:5: 错误: 无法为最终变量address分配值
people.address = new Address();
^
1 个错误
【说明】:此时错误的原因是final修饰的address指向的对象被修改了,所以程序出现错误。如图22-2所示。
图22-2
继续修改程序:
public class FinalTest3{
public static void main(String[] args){
People people = new People();
// people.age = 20;
// people.address = new Address();
people.address.name = "shanghai";
}
}
class People{
//final int age = 10;
final Address address = new Address();
}
class Address{
String name = "Beijing";
}
编译结果成功
【说明】:此时final关键字修饰的引用没有被修改,修改的只是指向的这个对象的值被修改了,所以final修改的这个指向地址是没有变化的,所以程序编译成功。如图22-3所示。
图22-3
7. 当final修饰一个原生数据类型时,表示该原生数据类型的值不能发生变化比如说不能从10变为20);如果final修饰一个引用类型时,表示该引用类型不能再指向其他对象了,但该引用所指向的对象的内容是可以发生变化的。