阅读理解代码
class A {
static int m;
static void f() {
m = 10;
System.out.println(m);
}
}
class B extends A {
// 子类同名方法要么重载,要么隐藏
// 静态成员不会被继承,重写继承的父类方法
// void f() { // 标红报错
// m = 20;
// System.out.println(m);
// }
static void f() { // 程序正常
m = 20;
System.out.println(m);
}
}
public class E {
public static void main(String[] args) {
A.f(); // 10
}
}
abstract class A {
abstract float getFloat();
}
public class B extends A {
private float m = 1.0f;
@Override
// 方法重写注意事项:访问修饰符、返回值类型、异常类型
// private float getFloat() { // 标红报错
float getFloat() {
return m;
}
}
class A {
public int i = 0;
public A(int m) {
i = 1;
}
}
public class B extends A {
public B(int m) {
// 父类没有无参构造方法时,子类构造方法中必须显示使用super调用父类构造方法
super(m);
i = 2;
}
public static void main(String[] args) {
B b = new B(100);
System.out.println(b.i); // 2
}
}
class A {
double f(double x, double y) {
return x + y;
}
static int g(int n) {
return n * n;
}
}
class B extends A {
@Override
double f(double x, double y) {
double m = super.f(x, y);
return m + x * y;
}
static int g(int n) {
int m = A.g(n);
return m + n;
}
}
public class E {
public static void main(String[] args) {
B b = new B();
System.out.println(b.f(10.0, 8.0)); // (10.0+8.0)+10.0*8.0=98.0
System.out.println(b.g(3)); // 3*3+3=12
A a = new B();
//(10.0+8.0)+10.0*8.0=98.0 上转型对象调用子类重写的方法
System.out.println(a.f(10.0, 8.0));
// 3*3=9 静态成员不会被继承,静态成员属于类,而不是类的实例
System.out.println(a.g(3));
}
}
class A {
int m;
int getM() {
return m;
}
int seeM() {
return m;
}
}
class B extends A {
int m;
@Override
int getM() {
return m + 100;
}
}
public class E {
public static void main(String[] args) {
B b = new B();
b.m = 20;
System.out.println(b.getM()); // 120
A a = b;
a.m = -100;
// 上转型对象调用子类继承或重写的实例方法
System.out.println(a.getM()); // 120
System.out.println(a.seeM()); // -100
}
}
访问静态成员
子类中可以直接访问父类的静态成员,也可以通过父类或子类名
实现类中可以直接使用接口常量,但静态方法必须使用接口名调用
// 父类 Parent
public class Parent {
// 静态变量
static int num = 66;
// 静态方法
static void methodStatic() {
System.out.println("methodStatic...");
}
}
// 子类 Child
public class Child extends Parent {
public void method() {
// 在子类中直接访问父类的静态成员
System.out.println(num);
methodStatic();
// 在子类中使用父类名称访问父类的静态成员
System.out.println(Parent.num);
Parent.methodStatic();
// 在子类中使用子类名称访问父类的静态成员
System.out.println(Child.num);
Child.methodStatic();
}
}
// 接口 MyInterface
public interface MyInterface {
// 常量 [public][static][final]
public static final int MAX = 100;
// 静态方法 [public] static
public static void methodSta() {
System.out.println("methodSta...");
}
}
// 实现类 MyInterfaceImpl
public class MyInterfaceImpl implements MyInterface {
public void method() {
System.out.println(MAX);
MyInterface.methodSta();
// methodSta();
// 标红报错 Static method may be invoked on containing interface class only
}
}
继承 OR 实现
一、继承与实现的比较
继承(Inheritance)
- 继承是从已有类(父类或超类)创建新类(子类)的过程
- 子类继承父类的所有非私有属性和方法,同时可以定义自己的新属性和方法
实现(Implementation)
- 实现是指一个类遵循某个接口规范的过程
- 接口在Java中是一种定义行为的抽象类型
1、耦合度:继承可能导致类之间的耦合度增加,实现允许类之间更松散的耦合
2、扩展性:通过实现接口,可以更容易地扩展类的行为
继承在扩展时可能需要更复杂的操作,如子类化、覆盖方法等
3、单一职责原则:接口通常遵循单一职责原则,定义清晰的行为边界。继承可能导致类承担过多的职责
4、“是什么”与“做什么”:继承更适合表达“是什么”的关系,例如狗是动物。实现更适合表达“做什么”的关系
二、继承与实现的选择
在Java中,继承和实现是两种重要的代码重用和扩展机制
各自有其优势和适用场景,选择哪种机制取决于具体的需求和设计考虑
考虑代码的耦合度、扩展性、复用性以及设计原则(如单一职责原则、开闭原则等)
在Java中,通常更推崇对象组合和接口实现,而不是类继承
这是因为接口定义了行为,而不是实现细节,有助于降低类之间的耦合度,提高代码的可扩展性和灵活性
如果从子类优先使用父类方法的角度来看,继承确实有其独特的优势,但也需要谨慎使用,避免过度依赖