总结
final
概念:最后的、不可更改的
final修饰类:此类不可被继承
final修饰方法:方法可以被继承,但是不可以被覆盖。
final修饰变量:此变量值不能被改变(无初始值,只允许赋值一次)
final修饰变量赋值的方法:
局部常量:显示初始化
实例常量:显示初始化,动态代码块,构造方法(注意,如果在构造方法中为实例常量赋值,必须保证所有构造方法都能对其正确赋值)
静态常量:显式初始化,静态代码块
基本数据类型常量:值不可变
引用数据类型常量:地址不可变
接口
概念:接口相当于特殊的抽象类,定义方式、组成部分与抽象类类似
使用interface定义接口 ex:interface 接口名{}
接口没有构造方法,不能创建对象。
接口中只能定义公开静态常量和公开抽象方法
接口与抽象类的异同
相同
可编译成字节码文件(.class)
不能创建对象
可以作为引用类型
具备Object中所定义的方法
不同
所有属性都是公开静态常量,隐式使用public static final修饰
所有方法都是公开抽象方法,隐式使用public abstract修饰
没有构造方法,动态代码块,静态代码块
微观概念:接口是一种能力和约定
接口的定义是代表了某种能力
方法的定义是对能力的具体要求
经验:Java为单继承,当父类的方法种类无法满足子类需求时,可实现接口扩充子类能力。
接口支持多实现,可为类扩充多种能力
接口的规范
任何类在实现接口时,必须实现接口中的所有方法,否则此类为抽象类
实现接口中的抽象方法时,修饰符必须为public
接口的引用
同父类一样,接口也可声明引用,并指向实现类对象
注意:仅可调用接口中所声明的方法,不可调用实现类中独有的方法
可强转为实现类本身,进行独有的方法调用
---------------------------------------------------------------我是作业分割线
Q7
7.(final 属性的初始化)有如下代码
1)class MyClass{
2)final int value;
3)public MyClass(){}
4)public MyClass(int value){
5)this.value = value;
6)}
7)}
8)public class TestMain{
9)public static void main(String args[]){
10)MyClass mc = new MyClass(10);
11)System.out.println(mc.value);
12)}
13)}
选择正确答案:
A.编译通过,输出 10
B.编译不通过,把第 2 行改为 final int value = 10;
C.编译不通过,把第 3 行改为 public MyClass(){ value = 10; }
答案:C 如果在构造方法中为实例常量赋值,必须保证所有构造方法都能对其正确赋值
8.(final 变量)有如下代码 class MyClass {
public void printValue(final int value){
System.out.println(value);
}
public void changeValue(int value){
value = value * 2;
System.out.println(value);
}
}
public class TestMain{
public static void main(String args[]){
MyClass mc = new MyClass();
int value = 5;
final int fvalue = 10;
mc.printValue(value); //1
mc.printValue(fvalue); //2
mc.changeValue(value); //3
mc.changeValue(fvalue);//4
}
}
选择正确答案
A.编译通过
B.//1 出错
C.//2 出错
D.//3 出错
E.//4 出错
答案:E 因为实例常量的值不可以被改变
9.(final 修饰引用)有如下代码 class MyValue{
int value;
}
public class TestFinal{
public static void main(String args[]){
final MyValue mv = new MyValue();
mv.value = 100;
//1
System.out.println(mv.value);
}
}
下面说法正确的是:
A. 编译不通过 。
B. 编译通过。在//1 处加上:mv.value = 200; 则编译不通过
C. 编译通过。如果在//1 处加上:mv = new MyValue(); 则编译不通过。
答案:C
引用类型常量地址不可改变,里面的值可以改变。
10.(final 方法,方法覆盖)有如下代码 class Super{
public final void m1(){
System.out.println(“m1() in Super”);
}
public void m1(int i){
System.out.println(“m1(int) in Super”);
}
}
class Sub extends Super{ public void m1(int i){
System.out.println(“m1(int) in Sub”);
}
public void m1(double d){ System.out.println(“m1(double) in Sub”);
}
}
public class TestMain{
public static void main(String args[]){
Sub s = new Sub();
s.m1();
s.m1(10);
s.m1(1.5);
}
}
答案:
m1() in Super
m1(int) in Sub
m1(double) in Sub
13.(修饰符综合)下列方法声明中正确的是:
A.abstract final void m()
B.public void final m()
C.static abstract void m()
D.private final void m()
E.private abstract void m()
F.public static final void m()
答案:DF
A不对是因为abstract修饰的方法就是让子类重写,但是final修饰的不让子类重写
B不对,修饰符的顺序 方法修饰符 返回值类型 方法名(){} void与final位置不对, B的返回值类型会报错
C同理 static修饰的方法也不允许重写
D 解释一下D,private是本类可见,但本类可修改,加上final就是仅本类可见且不可修改的方法。
E private修饰的方法仅本类可见,而abstract需要子类去重写该方法,子类不可见就无法完成重写。故而矛盾
Q8
1.代码改错: interface IA{
void m1();
int a = 100;
}
class MyClass implements IA{
void m1(){}
}
public class TestInterface{
public static void main(String args[]){
IA ia = new MyClass();
ia.m1();
System.out.println(IA.a);
}
}
答案:需要在MyClass类中将方法前面加public,实现接口中的抽象方法时,修饰符必须为public
2.代码填空: interface IA{
void m1();
void m2();
}
_____ class MyClassA implements IA{
public void m1(){}
}
class MyClassB extends MyClassA{
_______________ {}
}
答案:第一个空填abstract,第二个填public void m2(){}
因为第一个类中没有完全覆盖引用接口中的方法,所以是个抽象类,需要加abstract修饰符,第二个类没有abstract修饰符,证明将接口方法完全覆盖了,故而将MyClass没有覆盖的方法进行覆盖。