Java复习之Java深入解析四(方法的重载、重写,静态的隐藏、构造器、初始化等)

  1. main方法:main方法是程序执行的入口。可以被重载,但必须要有虚拟机能自动调用的main方法才能编译通过。main方法也可以被其他方法调用。main同样也可以被继承和隐藏。
  2. 方法的重载:重载是根据参数列表的不同来区分的。参数列表的不同可以区分为个数、类型、顺序等。不能根据返回值类型和方法的异常列表来区分。
    void m(List ist){}
    void m(List<String> list){}
    以上两个方法也不能构成重载,因为参数化类型在经过编译后会被擦除。这两个方法擦除后的参数列表时相同的,都是List类型,会出现方法重定义。
    在调用重载方法的时候,会最先调用最“明确”的方法。如实参为byte类型时的调用,形参中没有byte类型的时候,会依次找short、int、long、float、double。实参为char类型时的调用,会依次找char、int、long、float、double。找到为止。参数为引用类型时也一样。先找形参为该类的引用的方法。如果没有,再找可以赋值的父类的引用的方法。
    自动拆装箱和可变参数类型的重载:优先选可变参数类型
public class Maintest {
    public static void main(String[] args) {
        Maintest maintest=new Maintest();
        int i=10;
        maintest.m(i);
    }
   public void m(Integer integer)
   {
       System.out.println("Integer\t\t"+integer.intValue());
   }
    public void m(long l)
    {
        System.out.println("long\t\t"+l);
    }
}

运行结果为:

long		10

当调用方法有有两个或两个以上的参数,且多个方法都符合调用条件,但是无法从中选择出一个最明确的方法来调用时。就会产生编译错误。

public class Maintest {
    public static void main(String[] args) {
        char ch='a';
        int i=1;
        long l=2;
        float f=3;
      //m(ch,l);
    }
    public static void m(char ch,float f)
    {
        System.out.println("char-----float 方法");
    }
    public static void m(int i,long l)
    {
        System.out.println("int------long 方法");
    }
}

这样的方法调用产生了编译错误。因为两个方法都不是最明确的,但都可以调用。因此不明确该调用哪一个。注释两个方法中的任意一个,就会调用剩下的一个。编译即可通过。
重载方法的调用是根据引用的静态类型来决定的(标识符左边的类型),这一点与对方法重写的调用不同(多态,运行时决定)。

public class Maintest {
    public static void main(String[] args) {
       Object o=new String();
       m(o);
    }
    public static void m(String s)
    {
        System.out.println("String");
    }
    public static void m(Object o)
    {
        System.out.println("Object");
    }
}

运行结果为Object。是根据引用的静态类型来决定的。
3.方法的重写:
重写条件:

  • 都要是实例方法,不能是静态。
  • 子类方法的返回值类型是父类方法的返回值类型的可替换类型。
  • 不能比父类抛出更多的异常。
  • 子类方法的访问权限不能低于父类方法的访问权限。

可以在子类中使用非泛型化的方法重写父类中泛型化的方法,但是不能再子类中使用泛型化的方法重写父类中非泛型化的方法。父类定义为void m(List<String> list)时,子类可以重写为void m(List list)。但是反过来不行。要重写父类的方法,在子类中首先要可以访问到。父类中私有的方法不能重写,可以在子类中定义与父类中私有方法同名同参的方法,但这不是重写,是重新定义了一个方法。
4.隐藏:
方法的隐藏:条件和方法的重写条件一样,只不过两个方法都是静态的。
成员变量的隐藏:从父类中继承来了(不是private修饰的)且变量名称相同就是隐藏。
对于隐藏的变量和方法来说,要调用时通过类名点变量名来调用。
父类:

public class Super {
    public String s="Super 的成员变量";
    public void m(){
        System.out.println("Super 的m方法");
    }
    public static void method(){
        System.out.println("Super的静态方法");
    }
}

子类:

public class Maintest extends Super{
    public String s="Maintest 的成员变量";
    @Override public void m() {
        System.out.println("Maintest 的方法");
    }
    public static void method()
    {
        System.out.println("Maintese的静态方法");
    }
    public static void main(String[] args) {
        Super s=new Maintest();
        System.out.println(s.s);
        s.m();
        s.method();
    }
}

运行结果:

Super 的成员变量
Maintest 的方法
Super的静态方法

对于隐藏,是根据引用的静态类型来决定调用相关类的成员。

5.构造器:构造器在创建对象之后调用,对对象进行初始化工作。所以不是构造器创建对象,而是new关键字创建了对象。构造器可以显示调用,用this(调用当前类的构造)或者super(调用父类构造)。但是this或super必须出现在构造器中的第一行。所以this和super不能同时出现在一个构造方法中。如果类内没有构造方法时,系通或生成无参构造。这个无参构造会调用父类的构造,一直递归,直到调用到Object类。
父类:

public class Super {
   public Super()
   {
       System.out.println("This is Super's constructor");
   }
}

子类,没有写构造方法。系统自动生成无参构造。但是如果有有参构造,系统不会自动生成无参构造。所以如果写了有参构造,最好顺便添加上无参构造。

public class Maintest extends Super{
    public static void main(String[] args) {
     Maintest maintest=new Maintest();
    }
}

运行结果:

This is Super's constructor

6.成员变量的初始值:
基本数据类型:数字类型的均为0,char为空字符,boolean为false。
引用数据类型:数组和对象的引用均为null。
在方法中声明的局部变量没有默认值,使用前一定要赋初始值。但是数组有值,值为0。
实例变量初始化方式:

  • 在声明处初始化。
  • 在实例化块中初始化。
  • 在构造方法中初始化。

静态变量的初始化方式:

  • 在声明处初始化。
  • 在静态初始化块中初始化

五种初始化的先后顺序:先静态,后实例,最后剩下构造器。静态和实例中方法和变量的顺序是以定义顺序为初始化顺序。

public class Maintest {
    public static int i=Super.init2();
    public Maintest()
    {
        System.out.println("构造器初始化");
    }
    static {
       System.out.println("静态块的初始化");
   }
    {
        System.out.println("实例块初始化");
    }
    public int j=Super.init1();
    public static void main(String[] args) {
        Maintest maintest=new Maintest();
    }
}

不管怎样调整调整以上五段初始化代码的顺序,构造器都是在最后,静态都是在实例之前。JVM虚拟机试图调用该类的main方法,发现类没有被加载。因此会先加载类,为类的静态变量分配空间,并设置默认值,随后初始化执行。静态初始化部分只会在加载类的时候进行执行。实例初始化部分会在创建对象的时候执行。
运行结果:

静态变量初始化
静态块的初始化
实例块初始化
实例变量初始化
构造器初始化

当存在继承关系时,先调用父类的静态,后调用子类。当存在引用时。
向前引用:在定义变量之前就引用了该变量。变量的值为默认值。访问时要加this。
在构造器中调用了实例方法,该实例方法用到了实例成员变量。由于构造器是对实例变量的初始化,因此这种情况也被视为向前引用。

public class Maintest {
   private int area=this.side*4;
   private int side=5;
   public static void main(String[] args) {
       Maintest maintest=new Maintest();
        System.out.println("side:"+maintest.side+"\tside:"+ maintest.area);
    }
}

由于是在同一个类,公有可以访问私有。成员变量数字基本类型中数字类型的默认值为0。

side:5	side:0

如果有final修饰的变量出现,则该变量即为常量。在编译成字节码的时候值就已经定了,且不可更改。所以在程序运行的时候,根本看不见final修饰的变量的默认值。就算是向前引用也看不到。

上一篇
---The End---
下一篇
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值