JavaSE学习笔记-04

断点调试:

步骤:

 首先确定断点

然后右键debug

细节展示:

 

Resume:直接执行到下一个断点

红色小方块:停止debug调试

 

 表示往下走,往下进行调试。

————————————————————————————————————————

 进入源码的方法,每一次强制进入一层方法

 ——————————————————————————————————————————

 当我们想要在源码方法中进行调试的时候,我们要下断点(一定不要忘记下断点再进行调试)然后进行f7调试。

 

 上图中的调试键就是如下图作用:

 当我们想要一步一步的进入到源码方法的时候,我们必须要在每一个类中的方法进行添加断点,然后才能进行调试 

 

我们先回顾记一下对象创建的流程:

本章作业:

1.

 源码:

public class Personleomessi {
    public static void main(String[] args) {
        leomessi[] leo=new leomessi[3];
        leo[0]=new leomessi(10,"tom");
        leo[1]=new leomessi(34,"messi");
        leo[2]=new leomessi(29,"eriksen");
        /**
         * 普通输出
         */
        for (int i = 0; i <leo.length; i++) {
            System.out.println(leo[i]);
        }
        /**
         * 冒泡排序
         */
       leomessi tmp=null;//定义一个临时变量
        /**
         * 默认要排序n-1个,因为前n-1个排序完成之后,最后一个肯定是有顺序的了。
         */
        for (int i = 0; i < leo.length-1; i++) {
            for (int j = 0; j < leo.length-i-1 ; j++) {
                /**
                 * 我们想要按照年龄为准则从大到小进行输出
                 */
                if(leo[j+1].getAge()>leo[j].getAge()){
                    /**
                     * 把对象进行交换
                     */
                    tmp=leo[j+1];
                    leo[j+1]=leo[j];
                    leo[j]=tmp;
                }
            }
        }
        for (int i = 0; i <leo.length; i++) {
            System.out.println(leo[i]);
        }
    }
}
class leomessi{
    private int age;
    private String name;

    public leomessi(int age, String name) {
        this.age = age;
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "leomessi{" +
                "age=" + age +
                ", name='" + name + '\'' +
                '}';
    }
}
      /**
         * 选择排序
         */
       leomessi tmp=null;//定义一个临时变量
        int j = 0;
        for (int i = 0; i < leo.length-1; i++) {
            int min=0;
            for (j=0; j < leo.length-i-1 ; j++) {
                if(leo[j].getAge()<min){
                 min=j;
                }
            }
            /**
             * 每一次把最小的值都放到最后面
             */
            tmp=leo[min];
            leo[min]=leo[leo.length-1-i];
            leo[leo.length-1-i]=tmp;
        }

我们对修饰符的访问机制探讨分为四部分:同类 同包 子类  不

private 只可在同一个类中才可进行访问 

快捷键生成一个对象 

代码:

 教授类:

测试类:

 本题的核心难点在于经理的奖金应该是变化的,所以我们不应该在构造器中给定死

我们应该用set方法在后面测试类中随机应变的给定

测试类:

经理类:

主类:

第五题是一个重点,要吃透。。。。。

 老师的年薪==每节课的课时费以及每一年上课的天数总数+月薪*带薪月份

 

 ————————————————————————————————————————

 

分析一下:

首先明确一点:this是代表当前对象的引用,super代表父类对象的引用

因此我们可知:

this进行访问的时候,是从当前对象开始逐级向上访问的;super是从父类开始逐级向上进行访问的 

Father类:

super从父类开始向上访问

其中super不可以访问age,因为age是私有的,只可以在本类中访问

this从本类开始访问,也是除了age都可以访问

Son类:

super从父类Father开始访问,除了私有的其他都可以进行访问

this:从本类开始访问:

除了私有的不可以访问之外。

我们还要特别注意一点:当我们向上访问到爷类Grand的时候,发现name属性和g1方法都是在Son类中出现了,那么Son类中相当于进行了重写。。。。那么只能访问一次,不可以进行重复的访问。。。。。

因此总结:

我们对于相同的方法或属性的访问只能访问一次。。。。

————————————————————————————————————————

从main方法开始分析:

先new Demo(),在创建一个对象的时候,会进入构造器,分析得知这里是无参构造器。那么进行无参构造器分析,super()表示调用父类的无参构造器Test();故先打印 Test ;创建对象之后并没有赋值给一个对象引用,因此这是一个匿名的对象,再调用test方法,打印即可。

再分析下面那一个创建的匿名对象,他创建对象的时候调用的是有参构造器,有参构造器调用的是父类的有参构造器,我们知道属性是没有动态绑定机制的。这里的this.name就是代表父类的属性name的调用,这里改为john。然后test方法打印,打印John和Jack(咱们假设一下,假如说这里是get()方法,然后父类和子类都有这个方法,那么又由于动态绑定机制,当super调用到父类的时候,我们还是反回去调用子类的绑定的方法get(),因为方法有动态绑定机制。)

第一问:

 BankAccount类:

扩展一个新的账户:

测试类:

 

 第二问:

 9.

 测试类:

 

每一个类都是Object类的子类。这里的重写父类的equals()方法相当于就是重写Object的equals方法

代码:

1.先创建成员列表并且提供构造器和get set方法

2.

 在最后的返回时,我们要注意:基本数据类型只可以用 == 进行比较;只有引用数据类型才可以进行equals方法进行比较

本题中instanceof方法解释一下:

假设原来的obj是这样创建的  Object obj=new Doctor();那么这个obj的运行类型是Doctor,编译类型是Object。我们把这个obj传进去给equals方法。。。。

每一次调用重写的equals方法,传过来的是不同的对象,那么obj也不同。Object只是obj的编译类型,obj instanceof(Doctor)表示的意思是:obj这个对象引用的运行类型(即右边的类型)是否为关键字右边类型或是右边类型的子类类型  。

 如下图所示:

  例子:

 当用一个对象引用进行调用方法的时候,该方法会和该对象的运行类型产生绑定,只会进行运行类型中的方法,而不是编译类型中的方法,这就是运行时绑定

这也就是为什么,编译时看左,运行时看右。

编译是由编译器完成的一项任务,编译器只认编译类型,因此但凡编译类型的类不包含的方法,无法调用,一旦调用直接报错。因此我们引入这个不安全的向下转型,所谓向下转型就是为了解决这个问题,搞出来的对象引用,既可以调用父类的方法也可以调用子类的独有的方法。。。。

_______________________________________________________________________

在向下转型中:我们用到instanceof关键字:p instanceof(Person)。左边的p是一个对象引用,我们用Person p=new Student();把它创建,但是我们instanceof判断的是 p的运行类型(Student)是否为右边Person类型或者是否是右边Person类的子类  如果返回true那么才可以进行向下转型:Student leo=(Student)p;

_____________________________________________________________________________

但是当我们运行起来的时候,就应该看右了:这就是运行时绑定,对象引用调用方法的时候,该方法和该对象的运行类型产生绑定。母庸质疑,运行类型是右边的类型。。。

说了这么多,,,,,其实也就一个核心思想,好好理解一下吧。

 ==既可以比较基本数据类型又可以比较引用数据类型

equals只可以比较引用数据类型

 第三步:把子类中公共部分抽取到父类Person中

 Person:

 学生:

 第七问:

 第八问

创建一个对象,我们可知它调用的是无参构造器,,this("hello"):表示的意思是调用子类的有参构造器,

重点:注意我们这里已经this("hello")调用本类的有参构造器了,那么我们就不会再默认进行调用super()了,为什么这样说?因为this和super调用构造器的时候我们都有一个要求就是放在第一行,所以二者不可共存

super("hahah") 表示的意思是调用的父类的有参构造器,我们知道构造器中的第一行都会是super()默认调用父类的无参构造器,只是这里省略了。所以这一步分析要小心了。。。。。

最后打印的顺序如图所示即可,,,,,

隐藏的super();注意了啊:

如图obj的运行类型是可以变化的,但是编译类型是不可以进行改变的。。。。

getclass是用来获取运行类型的

 当调用对象的方法的时候,该方法会和对象的内存地址或者运行类型绑定。

 当调用对象的方法的时候,该方法会和对象的内存地址或者运行类型绑定。如上图所示:obj的运行类型是CCC,发生向上转型。

我们知道调用方法的时候发生动态绑定机制,对于一个对象引用obj,它调用xxx()这个方法的时候

我们第一步是先看obj的运行类型,显然它的运行类型是CCC,那么obj和运行类型CCC绑定,当调用方法的时候,我们先从运行类中开始找,如果没有接着顺着向上找,找父类,向上找。。。。

如图所示:如继承关系一样的方法信息查找

——————————————————————————————————————————

何为向上转型?

父类的引用指向了子类的对象

格式:父类类型  对象引用=new 子类类型();

 何为向下转型?

将父类引用强制转化为子类类型,并且赋给对象引用

格式:子类类型  对象引用=(子类类型)父类引用;

———————————————————————————————————————————

 对于属性,当一个对象引用调用对象的属性的时候,没有动态绑定机制,我们遵从哪里声明,哪里使用。。。在哪一个类中声明的,我们就在哪里进行使用这个属性。。。。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值