断点调试:
步骤:
首先确定断点
然后右键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"):表示的意思是调用子类的有参构造器,super("hahah") 表示的意思是调用的父类的有参构造器,我们知道构造器中的第一行都会是super()默认调用父类的无参构造器,只是这里省略了。所以这一步分析要小心了。。。。。
最后打印的顺序如图所示即可,,,,,
隐藏的super();注意了啊:
如图obj的运行类型是可以变化的,但是编译类型是不可以进行改变的。。。。
getclass是用来获取运行类型的
当调用对象的方法的时候,该方法会和对象的内存地址或者运行类型绑定。
当调用对象的方法的时候,该方法会和对象的内存地址或者运行类型绑定。如上图所示:obj的运行类型是CCC,发生向上转型。
我们知道调用方法的时候发生动态绑定机制,对于一个对象引用obj,它调用xxx()这个方法的时候
我们第一步是先看obj的运行类型,显然它的运行类型是CCC,那么obj和运行类型CCC绑定,当调用方法的时候,我们先从运行类中开始找,如果没有接着顺着向上找,找父类,向上找。。。。
如图所示:如继承关系一样的方法信息查找
——————————————————————————————————————————
何为向上转型?
父类的引用指向了子类的对象
格式:父类类型 对象引用=new 子类类型();
何为向下转型?
将父类引用强制转化为子类类型,并且赋给对象引用
格式:子类类型 对象引用=(子类类型)父类引用;
———————————————————————————————————————————
对于属性,当一个对象引用调用对象的属性的时候,没有动态绑定机制,我们遵从哪里声明,哪里使用。。。