block与debug

block

块{},在java中自成作用域,可以分为

静态代码块 构造代码块 普通语句块 同步代码块
声明位置 类中,方法外 类中,方法外 方法中 fynchronized(){}
作用 整个类进行某些初始化操作(静态属性赋值...) 构造代码块是为对象初始化操作(为静态或非静态成员属性赋值...) 声明一些临时变量等.. 控制并发
执行时机 类第一次加载时,只执行一次,如果多个静态块,从上倒下一次执行 创建对象时,执行构造器代码之前执行,如有多个,从上倒下一次执行 跟随方法执行 跟对方法执行

注意:

  • 类第一次被载入时先执行static代码块;类多次载入时,static代码块只执行一次;static块经常用来进行static变量的初始化。

  • 是在类初始化时执行,不是在创建对象时执行。

  • 静态初始化块中不能访问非static成员。

  • 构造块被被编译到将要执行的构造器代码之前执行

静态块,仅在类的第一次使用时加载。
构造块,先于构造器执行,每创建一个对象执行一次

debug

在学习或开发过程中,遇到bug是避免不了的,为了能够快速调试,可以使用debug调试工具。

调试一个Java程序非常简单的,主要有设置断点、启动调试、单步执行、结束调试几步。

debug界面窗口:

block与debug_第1张图片1)设置断点

block与debug_第2张图片
2)启动调试

Eclipse提供几种方式来启动程序(Launch)的调试,分别是通过菜单(Run –> Debug)、图标(“绿色臭虫”)、右键->Debug As。

block与debug_第3张图片

弹出提示,需要切换到调试(Debug)工作区,勾选“Remember my decision”,记住选择,则下次不再提示,然后点击【Yes】。

block与debug_第4张图片

3)单步执行

主要使用前面讲过的几个视图进行调试,其中debug视图中的几个按钮有快捷键:

Step Return(F7) : 表示退出当前方法,返回到调用层。

Step Over (F6) : 表示运行下一行代码。

Step Into (F5) : 表示进入当前方法。

block与debug

4)结束调试

通过Terminate命令终止对本地程序的调试。

面向对象-继承性

继承

“树上一只鸟树下两只兔子,请问几种动物 , 请问几种生物?” 这里面就存在了继承的概念。

block与debug_第5张图片

继承:子承父业

继承的本质在于抽象。类是对对象的抽象,继承是对某一批类的抽象,从而实现对现实世界更好的建模。

继承的作用 : 使用继承可以提高代码的复用性。

如何使用继承:

父类|超类|基类:根据一些列子类抽象,抽取像的部分,定义在父类中

子类|派生类:子类继承父类,有权使用父类中的内容,可以定义子类新增内容,所以说子类是父类的延续+扩展

extends 关键字的意思是“扩展”。子类是父类的扩展。

java 中使用 extends 关键字实现类的继承机制,语法规则:

 class  [extends ]{} 
//父类
class Person{
    public String name;
    public int age;

    public void sleep(){
        System.out.println("休息");
    }
}
//子类
//教师类
class Teacher extends Person{
    public String subject;

    public Teacher() {
    }

    public void teach(){
        System.out.println("传授知识");
    }

}

//学生类
class Student extends Person{
    public String school;

    public Student() {
    }

    public void study(){
        System.out.println("在知识的海洋畅游!");
    }
}

注意:

  • 子类继承父类的成员变量和成员方法,但不继承父类的构造方法
  • java中只有单继承 ,没有像c++那样的多继承。多继承会引起混乱,使得继承链过于复杂,系统难于维护。就像我们现实中,如果你有多个父母亲,那是一个多么混乱的世界啊。多继承,就是为了实现代码的复用性,却引入了复杂性,使得系统类之间的关系混乱。
  • java中的多继承,可以通过接口来实现
  • 如果定义一个类时,没有调用extends,则它的父类是:java.lang.Object。

继承的特点:

优点:

  • 通过继承可以简化类的定义,实现代码的重用|提高代码复用性
  • 可以更好的扩展程序
  • 子类一旦继承父类,可以有权使用父类中的成员,也可以扩展定义子类独有内容
  • java是单继承继承,实现简单

缺点:

  • 子类与父类之间紧密耦合(耦合度高),子类依赖于父类的实现,子类缺乏独立性。
  • 不便于后期维护
  • 单继承一个子类只能有一个父类,不够灵活,不便于后期维护

super关键字

super

super是指向父类的引用。

super可以在子类构造器中调用父类某个构造器

如果构造方法没有显示地调用父类的构造方法,那么编译器会自动为它加上一个默认的super()方法调用。如果父类由没有默认的无参构造方法,编译器就会报错,super()语句必须是构造方法的第一个子句。

super可以用来区分子父类中同名成员

如果不存在同名问题,可以直接在子类中调用父类内容,super默认省略

如果存在同名问题,在子类中调用同名成员,默认this.恒源 调用当前子类同名成员,先要调用父类同名成员,必须定义为super.成员

//父类
public class Animal {
    int eye = 2;
    public Animal(){
        super();
        System.out.println("动物");
    }

    public void run(){
        System.out.println("动物有不同走路方式");
    }

    public static void main(String[] args) {
        Bird b = new Bird();
        b.run();
    }
}
//子类
class Bird extends Animal{
    public Bird(){
        super();
        System.out.println("鸟类");
    }

    public void run() {
        super.run(); // 通过super可以用父类方法和属性
        System.out.println("鸟是飞飞飞飞飞飞");
        System.out.println("鸟类有"+super.eye+"只眼睛");
    }

}

Bird--> Animal --> Object 图形分析如下
block与debug_第6张图片
构造方法调用顺序:

  • 根据super的说明,构造方法第一句 总是:super(…)来调用父类对应的构造方法。
  • 先向上追溯到Object,然后再依次向下执行类的初始化块和构造方法,直到当前子类为止。

this和super之间的区别

相同点:

  1. this和super都能用来调动其他共构造器,都要在首行出现
  2. this和super都可以用来区分同名问题,不区分同名时候可以省略
  3. this和super都指的是对象,所以,均不可以在static环境中使用。包括:static变量,static方法,static语句

块。

不同点:

  1. this(参数)构造器第一行调用本类中其他构造器,super(参数)构造器第一行调用父类中某个构造器
  2. this用来区分成员和局部同名问题,super用来区分子父类中同名问题

注意:

  • this和super不能同时出现在一个构造函数里面,因为this必然会调用其它的构造函数,其它的构造函数必然也会有super语句的存在,所以在同一个构造函数里面有相同的语句,就失去了语句的意义,编译器也不会过。

  • 从本质上讲,this是一个指向本对象的指针, 然而super是一个Java关键字

重写与final关键字

重写Override

父类的功能实现不满足子类的要求,可以在子类中按需改写,这就是方法的重写。

实现重写的三个条件:

  • 不同的两个类
  • 继承关系|实现关系

  • 方法签名相同

@Override:注解,强制检查是否为重写方法

注意:

  • 子类重写的方法会对父类的方法进行屏蔽。
  • 当子类对象调用时,会调用子类中重写的方法,子类没有找父类。
public class OverrideTest {
    public static void main(String[] args) {
        Sicong sicong=new Sicong();
        sicong.getMoney(); //调用子类中重写方法
    }
}
//父类
class Jianlin{
    public void getMoney(){
        System.out.println("先定一个小目标,赚他个一个亿");
    }
}
//子类
class Sicong extends Jianlin{
    @Override  //强制检查是否为重写方法
    public void getMoney(){
        super.getMoney();//在父类的原赚钱方法上扩展新功能,老功能不变
        System.out.println("我认识的人都没我有钱");
    }
}

重写的三个"=" :
“==”:方法名、形参列表相同。

“≤”:抛出的异常类型与返回值类型,返回值类型如果为基本类型必须相同,引用数据类型子类小于等于父类。

“≥”:访问权限,子类大于等于父类。

以下修饰符、修饰的内容不能重写:

  1. private修饰的方法不能被重写
  2. final修饰的方法不能被重写
  3. static修饰的方法不能被重写(子类如果出现和父类静态方法同名情况,那么子类中的方法也必须为静态的)

final关键字

final 表示最终的。

final可以用来修饰变量,方法,类。

修饰变量:变量一旦被初始化便不可改变,相当定义了一常量。

final int x=3;
//x=4; 常量不能改变

修饰方法 : final方法是在子类中不能被覆盖的方法

final void eat() { … }

修饰类,表示该类不能被继承

final class Person{ … }

Object类

Object 类是所有 Java 类的根基类

如果在类的声明中未使用 extends 关键字指明其基类,则默认基类为 Object 类

block与debug

toString(): 当打印对象的引用时,默认调用toString()方法

  • 默认返回:包名+类名+@+哈希码(根据对象的内存地址生成,唯一不重复)
  • 可以重写,实现义字符串的形式返回对对象(打印对象所有成员属性的值)
User p1=new User("张三",20);
System.out.println(p1);
//相当于
System.out.println(p1.toString());

equals:比较相等是否相等**

  • 默认地址比较(”第一个盒子的比较”)

  • 重写可以是实现比较两对象的内容是否一致
 object1.equals(object2) 
 如 : p1.equals(p2)
• 比较所指对象的内容是否一样,具体看equals的方法重写
 object1 == object2
 如:p1==p2
• 比较p1和p2的值即内存地址是否相等,即是否是指向同一对象。

注意:自定义类须重写equals(),否则无法实现比较其内容

class User{
    String name;
    int age;
    public User() {
        // TODO Auto-generated constructor stub
    }
    public User(String name, int age) {
        super();
        this.name = name;
        this.age = age;
    }
    //重写toString
    @Override
    public String toString() {
        return "User [name=" + name + ", age=" + age + "]";
    }
    //重写equals
    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        User other = (User) obj;
        if (age != other.age)
            return false;
        if (name == null) {
            if (other.name != null)
                return false;
        } else if (!name.equals(other.name))
            return false;
        return true;
    }
}