1.多态实现代码的重用
public class Animal {
public void eat(){}
}
public class Bird extends Animal{
public void eat(){
System.out.println("吃鸟粮");
}
public void m(){
System.out.println("鸣叫");
}
}
public class Dog extends Animal{
public void eat(){
System.out.println("吃狗粮");
}
public void f(){
System.out.println("狗吠");
}
}
public class Feeder {
//多态的作用
public void showFood(Animal a){
a.eat();
}
public void test(Animal a){
//向下造型,必须具有继承关系
/*
* Animal a = new Dog;
* Bird b = (Bird)a;
* 兄弟类之间不能进行强制转换,会出现类转换运行时异常
* Bird b1 = new Dog(); //编译错误
*
*
*/
if(a instanceof Dog){
((Dog) a).f();
}else if(a instanceof Bird){
((Bird) a).m();
}
}
}
public class Application {
public static void main(String[] args) {
Animal a = new Dog();
Animal b = new Bird();
Feeder f = new Feeder();
f.showFood(a);
f.showFood(b);
f.test(a);
f.test(b);
a.eat();
}
}
2.继承关系中构造方法调用
- 子类创建会调用父类的无参构造方法
- 如果父类没有调用无参构造方法,那么使用父类super()调用父类定义好的构造方法
public class Test {
}
class A{
}
//B会调A类的无参构造方法
class B extends A{
}
public class Test {
}
class A{
public A(int i){
}
}
class B extends A{ //报错Implicit super constructor A() is undefined for default constructor. Must define an explicit constructor
}
public class Test {
}
class A{
public A(int i){
}
}
class B extends A{
public B(){
super(1);
}
}
public class Test {
}
class A{
//这就是为什么一般定义两个构造方法
public A(){
}
public A(int i){
}
}
class B extends A{
public B(){
}
}
3. static关键字
static 修饰的变量(类变量)
在类加载的时候,分配内存,有默认值,可以访问。通常使用类名访问。静态变量在实例化之前
class A{
public void a(){
static int x; //错误,不能定义,但可以使用
}
}
- 问:静态变量好用,能不能在编程的时候多创建几个?
答:不能,静态变量存在于方法区中。不能被垃圾回收机制回收。为了节省空间,尽量少用静态变量 - 问:局部变量在for循环中初始化,可以否?
public void t(){
int i;
//编译不能识别,只能识别字面量
for(int j=0;j<3;j++)
i=j;
System.out.println(i);
} - 问:以下代码正确否?
答:没有static修饰的方法,叫实例方法;static修饰的方法在列加载的时候分配内存,可以有类名调用;在静态方法中不能使用this,super
public class Student {
int age;
String name;
static int count;
public Student(){
count++;
}
}
public class TestStudent {
public static void main(String[] args) {
Student s1 = new Student();
Student s2 = new Student();
Student s3 = new Student();
Student s4 = new Student();
System.out.println("创建了"+Student.count+"个对象");
}
}
静态块
- 完成静态变量初始化
- 静态块什么时候执行?
在类加载时执行,只执行一次
public class A {
static{
System.out.println("A1");
D d = new D();
}
{
System.out.println("A2");
}
public A(){
System.out.println("A3");
}
}
public class B extends A{
static C c = new C();
static{
System.out.println("B1");
}
{
System.out.println("B2");
}
public B(){
System.out.println("B3");
}
}
public class C {
public C(){
System.out.println("C");
}
}
public class D extends C{
public D(){
System.out.println("D");
}
}
public class Test {
public static void main(String[] args) {
new B();
}
}
结果:
A1
C
D
C
B1
A2
A3
B2
B3
- 静态变量的初始化过程
准备阶段:标识变量的值
初始化阶段:
public class Demo2 {
static int x = 9;
static{
x = 10;
y = 90;
z = 20;
}
static int y = 100;
static int z;
public static void main(String[] args) {
System.out.println(x+" "+y+" "+z);
}
}
static修饰的方法
- 重写:被隐藏了
- 重载:可以
- 继承:可以
3.final
- final可以修饰类、变量、方法
- 没有static的三种赋值方式(实例变量的常量的赋值):
- 多个构造方法的常量问题
- 静态成员变量的初始化
- final修饰的方法
- final修饰得方法不能被重写。数学的计算方法都是final,不能被重写
- final修饰的类是不能被继承的
4. 抽象类和接口
- 抽象方法:由abstract修饰的方法,叫抽象方法(不写不可以,接口貌似可以)
- 抽象方法的特点:没有方法体
- 抽象类:由abstract修饰的类,叫抽象类
- 抽象类的特点:不能创建对象
- 抽象类必须有子类来实现,要实现抽象类中的所有抽象方法,否则还得是抽象类
- final不能修饰抽象方法,因为final的方法不能被重写
- private没有方法重写,所以修饰方法也不行
- static修饰的方法被隐藏,不能被重写
- 抽象类中不是必须有抽象方法,但有抽象方法的一定是抽象类
5. 接口
接口没有构造方法,但抽象类有构造方法
接口的实现也是重写,千万不要以为他的访问权限默认,实现的时候也做成默认会出错