测试题:
1、简述重写的条件
a. 父子类
b. 方法名相同
c. 形参相同(个数、类型、顺序)
d. 返回值类型有关
基本数据类型,要求是一致
引用数据类型,子类的比父类的要小
e. 和修饰符有关
访问修饰符来说,子类的要比父类的要大
static修饰的方法不可以被重写
final修饰的方法不可以被重写
2、写出程序结果
public class Test2{
public static void main(String[] args){
new Demo().test();
new Demo("john").test();
}
}
class Test{//父类
String name = "Rose";
public Test(){
System.out.println("Test");
}
public Test(String name){
this.name = name;
}
}
class Demo extends Test{//子类
String name="Jack";//重名属性
public Demo(){
super();
System.out.println("Demo");
}
public Demo(String s){//John
super(s);
}
public void test(){
System.out.println(super.name);
System.out.println(this.name);
}
}
D:\javademo\day12_am>javac Test2.java
D:\javademo\day12_am>java Test2
Test
Demo
Rose
Jack
john
Jack
1. 初始化块
类的五大成员:成员变量、成员方法、构造器、初始化块、内部类
1.1 分类:
① 实例初始化块
每次实例化对象自动执行的一个代码块
语法:
{}
功能:对类中多个构造器中相同内容的复用性提高
特点:在构造器之前执行
如果有继承:
实例化子类的对象,会先执行父类构造器,在执行子类构造器
如果存在初始化块,父类初始化块-父类构造器-子类初始化块-子类构造器
② 类初始化块
在类加载(只加载一次)的时候自动执行的一个代码块(只执行一次)
语法:
static{}
特点:在类加载的时候只执行一次
用途:该类一旦被使用,就执行一段代码
如果有继承:
先加载父类在加载子类,所以先执行父类的类初始化块,在执行子类的
③ 超级情况:
存在父子关系,都有类初始化块和实例初始化块
如果是new子类对象的话!
执行顺序:父类的类初始化块->子类的类初始化块
->父类的实例初始化块->父类的构造器
->子类的实例初始化块->子类的构造器
//类加载(类初始化块),要比实例化对象(实例初始化块+构造器)靠前
//类初始化块和构造器,没有联系的!
2. 抽象类 ★
前提:Animal所有的子类都对eat方法进行了重写!Animal是为子类提供服务!
Animal类中的eat方法的,大括号还有用吗?没有用了!
将eat方法变为抽象方法
① 使用abstract修饰符修饰方法
② 将大括号删除,分号结尾
将类变为抽象类
① 使用abstract修饰符修饰类
特点:
① 抽象方法存在的类,必须是抽象类!
② 子类继承抽象类时,必须实现抽象类中所有的抽象方法
重写:父类有方法体,子类覆盖父类的方法体
实现:父类没有方法体,子类第一次指定方法体
③ 抽象类中可以有0-n个抽象方法或普通方法
④ 如果子类不能够实现抽象类中的抽象方法?
那么子类也必须变为抽象类
⑤ 抽象类是不能够实例化对象的!
⑥ 抽象类有构造器吗?有的!
抽象类不能够实例化对象,抽象类的使用必须是父类了!
所以构造器就是初始化子类对象的父类空间的
应用:一般作为模板工具类
模板:一部分是确定的,一部分是不确定的
练习:
计算任意一段程序的运行时间的模板!
计算时间的代码是确定的,任意一段程序是不确定的!
3. 权限修饰符
本类 本包 其他包(子类) 其他包(非子类)
public √ √ √ √
protected √ √ √ ×
缺省的 √ √ × ×
private √ × × ×
5. debug调试(非常重要,每个人都要会)
让程序单步运行!
① 打断点(你想让程序在哪个位置暂停)
② 采用debug模式运行
主要观察,程序的位置和变量的监控区(将当前变量的值显示在此处)
④ 执行的快捷键
F8 -> 单步运行(按一次、点一下运行一行代码)
F9 -> 找下一个断点(如果下面没有断点,一直到结束位置)
F7 -> 进入方法
shift+F8 -> 退出方法
随意剖析任意一段你不懂的代码!(需要耐心)
现在阶段,不用debug是可以搞定的,但是以后绝对不行!
示例:1. 初始化块
public class Person {
private String name;
//实例初始化块,每次实例化对象都会自动执行(和构造器差不多)
static{
System.out.println("10行代码");
}
static{
System.out.println("静态1");
}
{
System.out.println("这是父类的实例初始化块!");
}
{
System.out.println("实例1");
}
//类中有可能会存在多个构造器(需求需要)
//需求,在创建Person对象的时候,要执行一段代码(10 代码)
public Person(String name) {
System.out.println("这是name构造器");
this.name = name;
}
public Person(int id){
System.out.println("这是id构造器");
}
public Person() {
System.out.println("这是无参构造器");
}
}
public class Employee extends Person {
private double salary;
static{
System.out.println("这是子类的初始化块");
}
{}
public Employee(String name, double salary) {
super(name);
this.salary = salary;
System.out.println("这是子类的有参构造器");
}
public Employee() {
System.out.println("这是子类无参");
}
public static void method(){
System.out.println("这是。。。。");
}
}
public class Demo1 {
public static void main(String[] args) {
Employee.method(); //类加载吗?
System.out.println("------01------");
Person person=new Person();
Person person1=new Person("");
Person person2=new Person(5);
System.out.println("------02------");
Employee employee=new Employee();
Employee employee1=new Employee();
//类加载(类初始化块),要比实例化对象(实例初始化块+构造器)靠前
//类初始化块和构造器,没有联系的!
}
}
D:\javademo\day12_pm>javac Demo1.java
D:\javademo\day12_pm>java Demo1
10行代码
静态1
这是子类的初始化块
这是。。。。
------01------
这是父类的实例初始化块!
实例1
这是无参构造器
这是父类的实例初始化块!
实例1
这是name构造器
这是父类的实例初始化块!
实例1
这是id构造器
------02------
这是父类的实例初始化块!
实例1
这是无参构造器
这是子类无参
这是父类的实例初始化块!
实例1
这是无参构造器
这是子类无参
示例:2. 抽象类 ★
public abstract class Animal {
private int id;
private String name;
public Animal(){
System.out.println("无参");
}
/* Animal所有的子类都对eat方法进行了重写!
Animal类中的eat方法的,大括号还有用吗?没有用了!
public void eat() {
System.out.printli("吃饭呢");
}*/
public abstract void eat();
public void working(){
System.out.println("开干上午的工作");
this.eat();//调用的是谁的呢?this是谁?
System.out.println("开干下午的工作");
}
}
public class Dog extends Animal {
//父类中的eat方法,不能够满足我的情况,可以重写
public void eat(){
System.out.println("啃骨头");
}
//让下一代实现,相当于Dog有一个抽象方法,Dog必须变为抽象类
}
public class Cat extends Animal {
//父类中的eat也满足不了Cat
public void eat(){
System.out.println("吃鱼");
}
}
public class Demo2 {
public static void main(String[] args) {
Dog dog=new Dog();
dog.working();
Cat cat=new Cat();
cat.working();
}
}
D:\javademo\day12_pm>javac Demo2.java
D:\javademo\day12_pm>java Demo2
无参
开干上午的工作
啃骨头
开干下午的工作
无参
开干上午的工作
吃鱼
开干下午的工作
示例:抽象类应用
练习:
计算任意一段程序的运行时间的模板!
计算时间的代码是确定的,任意一段程序是不确定的!
public class Test1 {
public static void main(String[] args) {
User1 user1=new User1();
long time = user1.getTime();
System.out.println(time);
}
}
abstract class Time{
public abstract void code();
public long getTime(){
long start=System.currentTimeMillis();
//任意一段代码
code();
long end=System.currentTimeMillis();
return end-start;
}
}
class User1 extends Time{
@Override
public void code() {
for (int i = 0; i < 100000; i++) {
String str="abc";
str+="aaa"+i;
}
}
}
输出:
29