阅读如下代码
class HelloA{
public HelloA(){
System.out.println("HelloA");
}
{
System.out.println("I'm A Class");
}
}
class HelloB extends HelloA{
public HelloB(){
//super(); // 调用父类构造函数(1)
System.out.println("HelloB");
}
{
System.out.println("I'm B Class");
}
}
public class TestHelloB{
public static void main(String[] args) {
new HelloB();
}
}
1、代码new的是HelloB 所以进入HelloB类 子类的所有构造方法中都有一个隐藏的父类构造函数super() 2、进入HelloB的无参构造中---->super()--->HelloA 实例初始化的顺序 1>super() 2>显式赋值 3>普通成员代码块内容 4>构造器内容 2和3的位置谁的顺序在前面就谁先执行,但是1和4的顺序是固定的 3、执行HelloA中的代码块---->无参构造----->回到子类 4、执行HelloB中的代码快----->无参构造----->返回main函数
I'm A Class HelloA I'm B Class HelloB
阅读如下代码
public class TestFatherChild {
public static void main(String[] args) {
Father f = new Father();//(1)
Child c = new Child();//(2)
}
}
class Father {
public Father(){
System.out.println("father");
}
}
class Child extends Father{
public Child(){
System.out.println("child");
}
}
1、语句1进入father类的无参---->先输出fathe 2、语句2进入child类的无参----->有默认的super()---->去父类father 3、没有显式赋值和代码块 所以直接执行构造器内容---->输出father 4、回到child类---->同上 进入无参---->输出child
father father child
实例初始化运行结果分析
public class Test01 {
public static void main(String[] args) {
new Child("mike");
}
}
class People {
private String name;
public People() {
System.out.print("1");
}
public People(String name) {
System.out.print("2");
this.name = name;
}
}
class Child extends People {
People father;
public Child(String name) {
System.out.print("3");
father = new People(name + " F");
}
public Child() {
System.out.print("4");
}
}
1、进入child类---->super()---->进入People类无参 2、输出1---->回到child类-----> 3、输出3----->new People 4、进入Peoper有参---->输出2---->name =mikeF
答案:132
继承、属性同名问题
public class Test02 extends Father{
private String name = "test";
public static void main(String[] args) {
Test02 test = new Test02();
System.out.println(test.getName());
}
}
class Father {
private String name = "father";
public String getName() {
return name;
}
}
1、进入Test02()----->super()--->进入Father---->x显示赋值name = father------>没有代码块还有构造器内容 所以返回test02
2、name = test test.getName();------>子类没有 所以去父类找----->这个方法是父类里的所以 name是父类的赋值所以是father
实例初始化
public class Test03 {
public static void main(String[] args) {
new A(new B());//(1)
}
}
class A {
public A() {
System.out.println("A");
}
public A(B b) {
this();
System.out.println("AB");
}
}
class B {
public B() {
System.out.println("B");
}
}
1、(1)开始被混淆了 这样理解 B b = new B(); A a = new A(b); 从里到外运行 所以显示运行B类 无参 ---->super()没有 所以回到main中 new A();----->有参数 所以是进入A(B b)---->this()是调用A中的无参方法 所以输出A ----->再回到A(B b)中 输出AB 答案
B
A
AB
继承
public class Test04 {
public static void main(String[] args) {
Father f = new Father();
Son s = new Son();
System.out.println(f.getInfo());//1
System.out.println(s.getInfo());//2
s.setInfo("尚硅谷");//3
System.out.println(f.getInfo());//4
System.out.println(s.getInfo());//3
}
}
class Father{
private String info = "atguigu";
public void setInfo(String info){
this.info = info;
}
public String getInfo(){
return info;
}
}
class Son extends Father{
}
编译看左边 运行看右边
new 的是father所以 1>是atguigu
2>s.getInfo里面没有getInfo方法 所以去到父类 所以还是atguigu
3>s.setInfo已经在内存中赋值为尚硅谷 所以从s调用的get都变成了尚硅谷
4>f.getInfo还是atguigu没变
5>s.getInfo变成了尚硅谷
答案:
atguigu
atguigu
atguigu
尚硅谷
this和super
public class Test05{
public static void main(String[] args) {
Father f = new Father();
Son s = new Son();
System.out.println(f.getInfo());//1
System.out.println(s.getInfo());//2
s.test();//3
System.out.println("-----------------");
s.setInfo("大硅谷");//4
System.out.println(f.getInfo());//5
System.out.println(s.getInfo());//6
s.test();
}
}
class Father{
private String info = "atguigu";
public void setInfo(String info){
this.info = info;
}
public String getInfo(){
return info;
}
}
class Son extends Father{
private String info = "尚硅谷";
public void test(){
System.out.println(this.getInfo());
System.out.println(super.getInfo());
}
}
1>f.getInfo()-->去到father类调用getInfo ---->输出atguigu
2>s.getInfo()-->去到son类中调用geInfo 类中没有getInfo所以去父类--->父类有getInfo所以调用父类的 --->输出atguigu
3>s.test() 方法中有两个调用this.getInfo和super.getInfo son类中没有所以去父类 所以两个输出都是atguigu
4>s.setInfo(),s是在内存中新建的一个空间 所以s的setInfo已经变成了“大硅谷”
5>f.getInfo(),没有改变所以还是atguigu
6>s.getInfo(),第四行已经改变了值所以调用s.getInfo是daguigu
7>s.test(),--->到达son中的test方法中当前类没有getInfo所以去父类
但是s.setInfo已经被赋值了大硅谷 所以输出大硅谷
答案
atguigu atguigu atguigu atguigu ----------------- atguigu 大硅谷 大硅谷 大硅谷
第6题:this、super、重写
public class Test06 {
public static void main(String[] args) {
Father f = new Father();
Son s = new Son();
System.out.println(f.getInfo());//1
System.out.println(s.getInfo());//2
s.test();//3
System.out.println("-----------------");
s.setInfo("大硅谷");//4
System.out.println(f.getInfo());//5
System.out.println(s.getInfo());//6
s.test();//7
}
}
class Father{
private String info = "atguigu";
public void setInfo(String info){
this.info = info;
}
public String getInfo(){
return info;
}
}
class Son extends Father{
private String info = "尚硅谷";
public void setInfo(String info){
this.info = info;
}
public String getInfo(){
return info;
}
public void test(){
System.out.println(this.getInfo());
System.out.println(super.getInfo());
}
}
1> atguigu
2> 尚硅谷
3> 尚硅谷 atguigu
4> 已经修改了s.setInfo()所以 s.getInfo是大硅谷
5> atguigu
6> 大硅谷
7> 大硅谷 atguigu
答案:
atguigu 尚硅谷 尚硅谷 atguigu ----------------- atguigu 大硅谷 大硅谷 atguigu
第7题:this
public class Test07 {
public static void main(String[] args) {
Father f = new Son();//1
System.out.println(f.x);//5
}
}
class Father{
int x = 10;
public Father(){
this.print();//2
x = 20;
}
public void print(){
System.out.println("Father.x = " + x);
}
}
class Son extends Father{
int x = 30;
public Son(){
this.print();//3
x = 40;
}
public void print(){
System.out.println("Son.x = " + x);//4
}
}
1、第一行是多态 编译看左边 运行看右边 先看左边有啥方法 再看son有没有重写
1>调用son的无参 默认有一个super 所以去到父类 运行顺序 显式赋值 代码块 构造方法
显示赋值是10 没有代码块 所以是运行构造器 运行第二 第二在son中已经被重写了 所以运行重写了的 跳到第四 代码又是就近原则 这里面x还没赋值所以第一行是son.x=0
2、输出完成之后进入显式赋值 x=30在进入构造方法 所以进入第三 第三跳入第四 所以再次输出son.x=30
3、实例初始化不干涉属性 所以最后f.x=20
第8题:虚方法
public class Test08 {
public static void main(String[] args) {
A a1 = new A();//1
A a2 = new B();//2
B b = new B();//3
C c = new C();//4
D d = new D();//5
System.out.println("(1)" + a1.show(b));//6
System.out.println("(2)" + a2.show(d));//7
System.out.println("(3)" + b.show(c));//8
System.out.println("(4)" + b.show(d));//9
}
}
class A{
public String show(D obj){
return ("A and D");
}
public String show(A obj){
return "A and A";
}
}
class B extends A{
public String show(B obj){
return "B and B";
}
public String show(A obj){
return "B and A";
}
}
class C extends B{
}
class D extends B{
}
a1是A类型的 带入一个b 因为b是B类型的 因为A中没有B类型的方法 可以直接去找他的父类
4同下B类的show(d)先去B类中找找不到接收D类型的 那么向上找 A中也没有 那么就找能接受它的父类 所以是A and D
/*(1)A and A (2)A and D (3)B and B (4)A and D*/
虚方法
public class Test09 {
public static void main(String[] args) {
A a1 = new A();//1
A a2 = new B();//2
B b = new B();//3
C c = new C();//4
D d = new D();//5
System.out.println("(1)" + a1.show(b));//6
System.out.println("(2)" + a2.show(d));//7
System.out.println("(3)" + b.show(c));//8
System.out.println("(4)" + b.show(d));//9
}
}
class A {
public String show(C obj) {
return ("A and C");
}
public String show(A obj) {
return "A and A";
}
}
class B extends A {
public String show(B obj) {
return "B and B";
}
public String show(A obj) {
return "B and A";
}
}
class C extends B {
}
class D extends B {
}
第8 去b找show b中没有接收C类型的方法 因为B继承了A子类没有就想上找 A有 所以输出
A and C;
答案:
(1)A and A (2)B and A (3)A and C (4)B and B
类初始化和实例初始化混合
public class Student extends Person {
public int age = getAge();
public int getAge() {
System.out.println("Student getAge() 6");
return 0;
}
static String country = getCountry();
public static String getCountry() {
System.out.println("Student getCountry() 7");
return null;
}
static {
System.out.println("Student 静态代码块 8 ");
}
{
System.out.println("Student 普通代码块 9 ");
}
public Student() {
System.out.println("Student 无参 A");
}
}
class Student extends Person {
public int age = getAge();
public int getAge() {
System.out.println("Student getAge() 6");
return 0;
}
static String country = getCountry();
public static String getCountry() {
System.out.println("Student getCountry() 7");
return null;
}
static {
System.out.println("Student 静态代码块 8 ");
}
{
System.out.println("Student 普通代码块 9 ");
}
public Student() {
System.out.println("Student 无参 A");
}
}
先父类后子类 先类初始化后实例初始化
父类 类初始化--->子类初始化--->父类实例初始化----->子类实例初始化(注意重写 如果子类有重写那么就不输出父类直接去子类)
答案:
Person getCountry() 2
Person 静态代码块 3
Student getCountry() 7
Student 静态代码块 8
Student getAge() 6
Person 普通代码块 4
Person 无参 5
Student getAge() 6
Student 普通代码块 9
Student 无参 A
本文通过实例分析了Java和C#中代码的执行顺序,包括实例初始化、继承、this和super的使用、虚方法调用以及类初始化和实例初始化的混合情况。详细解释了在不同场景下,代码执行的逻辑,帮助理解这两门语言的运行机制。

1007

被折叠的 条评论
为什么被折叠?



