学习笔记——day09(抽象final接口)

it2022-05-05  144

常见面试题

final修饰静态常量进过方法

final 修饰的基本数据类型变量的值 无法进行修改的final 修饰的引用类型的变量 只保证地址不变 对象中的内容可以发生改变

代码

public class Test01 { //定义常量 final static int num = 10; final static Dog dog = new Dog("泰迪","棕黄色"); public static void main(String[] args) { fun(num ); //fun(dog); System.out.println("main"+dog); } public static void fun( ) { dog.setColor("黑色"); //dog = new Dog(); System.out.println("fun"+dog); } public static void fun( int num ) { num++; System.out.println(num); } } class Dog { private String type; private String color; public Dog() { } public Dog(String type, String color) { super(); this.type = type; this.color = color; } public String getType() { return type; } public void setType(String type) { this.type = type; } public String getColor() { return color; } public void setColor(String color) { this.color = color; } @Override public String toString() { return "Dog [type=" + type + ", color=" + color + "]"; } }

静态成员常量不会导致类加载

静态成员常量不会导致类加载静态成员常量的值在加载前无法确定 那么会导致类加载

代码

public class Test02 { final static int num = (int)(Math.random()*33); static { System.out.println("我是静态代码块"); } public static void main(String[] args) { System.out.println(Test02.num); } } public class Test03 { public static void main(String[] args) { System.out.println(Test02.num); } }

类的加载顺序

先加载静态内容 -> 先执行静态代码块 由于父子关系 所以子类加载之前需要先加载父类

执行的父类的初始化块和欧构造器

准备执行子类的构造器 (先执行初始化块 子类构造器中有一个super)

顺序 父类的静态代码块 子类的静态代码块 父类的初始化块 父类的构造器 子类的初始化块 子类的构造器

代码

public class Test04 { public static void main(String[] args) { new S2().m(); } } class F{ static { System.out.println("F static"); } { System.out.println("F init"); } public F() { System.out.println("F construct"); } } class S1 extends F{ static { System.out.println("S1 static"); } { System.out.println("S1 init"); } public S1() { System.out.println("S1 construct"); } } class S2 extends F{ static { System.out.println("S2 static"); } { System.out.println("S2 init"); } public S2() { System.out.println("S2 construct"); } public void m() { new S1(); } } 运行结果: F static S2 static F init F construct S2 init S2 construct S1 static F init F construct S1 init S1 construct

abstract抽象类

抽象类基础概念

1: 父类中定义的方法不需要具体的实现步骤 子类都不按照父类的做 2: 父类中定义这个方法的目的是告诉子类 一定要保证存在该方法

对于类的要求: 1:父类中不需要定义方法的实现步骤 2:子类必须要重写

抽象类: 包含了抽象方法的的类称之为抽象类。 被abstract修饰的类称之为抽象了

抽象方法: 只要方法的声明,没有方法体。 通过abstract修饰的方法称之为抽象方法

抽象类和抽象方法的关系: 有抽象方法的一定是抽象类; 抽象类不一定有抽象方法,也可以有普通的方法。

为什么需要抽象类? 避免子类的随意设计 提高了代码可读性 提高了子类的健壮性

代码

public class Test01 { } abstract class Person{ public abstract void eat() ; } class Chinese extends Person{ public void eat() { } } class En{ public void eat() { } }

深入理解抽象类

1:抽象类中只能包含抽象方法吗? 既可以定义抽象方法也可以定义普通方法2:是否可以定义构造器 抽象类可以存在构造器但是无法实例化 抽象类中的构造器是给子类准备的 抽象类就是用来被继承的 抽象方法就是被重写的3:子类继承了抽象了之后一定要重写所有的抽象方法

代码

public class Test02 { public static void main(String[] args) { // 实例化抽象类 //Father f = new Father(); Son s = new Son(); } } abstract class Father{ public Father() { System.out.println("我是抽象类的构造器"); } public abstract void study(); //public abstract void work(); } class Son extends Father{ public Son() { } public void study() { } }

模板方法:

将上下文中的一些不会变化的内容保留下来 在父类中实现并且定义整个程序的执行流程将核心的业务逻辑或者是算法逻辑延迟到子类中去实现。

代码

/* * 喝茶 烧水 冲泡 干了 * 喝咖啡 烧水 搅拌 干了 * */ public class Test03 { public static void main(String[] args) { /* * Tea t = new Tea(); t.flow(); * * Caf c = new Caf(); c.flow(); */ Water w1 = new Tea(); w1.flow(); } } abstract class Water{ private void fireWater() { System.out.println("咕噜咕噜咕噜"); } public abstract void pp() ; private void drink() { System.out.println("墩儿~墩儿~墩儿~墩儿~"); } public void flow() { fireWater(); pp(); drink(); } } class Tea extends Water{ public void pp() { System.out.println("冲泡"); } } class Caf extends Water{ public void pp() { System.out.println("搅拌"); } }

final

(final与abstract是对立的)

final修饰的变量称之为最终常量 在程序运行期间其值不可发生改变final修饰的类不可以被继承:太监类final修饰的方法不可以被重写

tips: 工具类一般不需要子类 工具方法一般不需要重写,但final在实际应用中较少

代码

public class Test01 { public static void main(String[] args) { String str = "991010010110"; } } /* final */ class Person{ public final void study() { System.out.println("必须早上5点起床"); } } class Student extends Person{ public void study() { System.out.println("这谁顶得住"); } }

接口

接口的简单定义

接口: 接口是一个规范 是一套标准 比抽象了还抽象

接口如何定义: 学习接口和学习类是一样的

接口定义:

1.修饰符 interface 接口名{} 2.接口中的变量都是公开的 静态的最终常量值 默认情况下变量都是public static final修饰 3.接口中可以定义静态方法(不建议1.8) 4.接口中定义的对象方法都是抽象方法 接口中的方法默认就是通过abstract修饰的 5.接口中的默认方法从1.8之后才开始被使用 允许在接口中定义default方法 而且存在方法体

代码

public class Test01 { public static void main(String[] args) { } } interface Fly{ int SPEED = 10; default void method() { } public static void fun1() { } public abstract void fun2() ; }

深入理解接口

修饰符 class 类名 extends 父类 implements 接口

接口深入:

1、类和接口直接通过implements 发生关系 类实现接口 2、类必须要实现接口中的所有抽象方法 3、一个类可以实现多个接口 类名 implements 接口1,接口2。。。。。 4、一个类实现了接口之后 要将当前接口以及接口的父接口中的所有抽象方法全部重写 5、接口可以多继承 6、接口无法实例化 7、接口没有构造器 8、接口中也可以使用多态

代码

public class Test03 { public static void main(String[] args) { Fly f = new SuperMan();//接口变量指向实现类对象 f.fly(); } } interface Fly extends Comparator,Serializable{ /* * public Fly() { * * } */ public void fly(); //public void method(); } class SuperMan implements Fly/* , Comparator */{ public void fly() { System.out.println("飒······"); } public int compare(Object o1, Object o2) { // TODO Auto-generated method stub return 0; } }

Tips:

接口就是一套规则,用来定义具体要做哪些事情,但是所有事情的具体实现都会延迟到实现类中完成。接口只需要定义has-a的关系,如果你是什么,则你具备了什么能力。

equals方法

equals方法就是用来比较两个对象是否相等的,默认Object的equals方法比较是两个对象的地址。 java.lang.NullPointerException 空指针异常 对象为null

ClassCastException 类型转换异常null可以强转为任意类型 null也可以是任意类型(不能强转为基本数据类型)

代码

public class Test01 { public static void main(String[] args) { //创建两个user对象 User u1 = new User("zhangsan","123"); User u2 = new User("zhangsan","123"); System.out.println(u1==u2);//== 比较两个对象的地址 System.out.println(u1.equals(u2)); String str = "哎~~~"; System.out.println(u1.equals(str)); User u3 = new User(); System.out.println(u3.equals(null)); } } class User{ private String name; private String pwd; public User() { // TODO Auto-generated constructor stub } public User(String name, String pwd) { super(); this.name = name; this.pwd = pwd; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPwd() { return pwd; } public void setPwd(String pwd) { this.pwd = pwd; } public String toString() { return "User [name=" + name + ", pwd=" + pwd + "]"; } @Override public boolean equals(Object obj) {//Object obj = u2; Object obj = "哎~~~"; if(!(obj instanceof User)) { return false; } //将obj强转为user User other = (User)obj; if(this.name!=null&&this.pwd!=null) { //比较用户名和密码 if(this.name.equals(other.name)&&this.pwd.equals(other.pwd)) { return true; } } return false; } }

最新回复(0)