面向对象---方法传参与构造器

方法详解

方法是类或对象的行为特征的抽象,方法是类或对象的重要组成部分。Java里的方法不能单独存在,在逻辑上要么属于类,要么属于对象。

方法的所属性:

Java语言是静态的,一个类定义完成后,只要不在重新编译这个类文件,该类和该类的对象所拥有的方法是固定的,永远都不会改变。执行方法时必须使用类或对象来作为调度者。
注意:同一个类中的方法之间相互调度时实际上还是this或者来作为调度者,只不过有时侯会省略,但实际上还是存在。

方法的参数传递机制:

Java中方法传递方式只有一种:值传递。所谓值传递就是将实际参数值的副本传入方法内,而参数本身不会受到任何影响。

package org.westos.practice;

public class valuetransform {

    public static  void swap(int a,int b){
        int tmp;
        tmp=a;
        a=b;
        b=tmp;
        System.out.println("a="+a+";"+"b="+b); //a=9;b=6

    }

    public static void main(String[] args) {
        int a=6;
        int b=9;
        System.out.println("a="+a+";"+"b="+b); //a=6;b=9
        swap(a,b);
        System.out.println("a="+a+";"+"b="+b); //a=6;b=9
    }

}

可以看到最终a,b的值并没有交换,只是传入及交换函数swap的a,b的两个副本值发生交换。

引用数据类型传参:

public class DataWrap {
    int a;
    int b;
}

测试类,交换a,b的值

package org.westos.practice;

public class DataWrapTest {
    public static void main(String[] args) {
        DataWrap dw=new DataWrap();
        dw.a=6;
        dw.b=9;
        swap(dw);
        System.out.println("a="+dw.a+";b="+dw.b);
    }

    private static void swap(DataWrap dw) {
        int tmp=dw.a;
        dw.a=dw.b;
        dw.b=tmp;
        System.out.println("a="+dw.a+";b="+dw.b);
    }
}
/*a=9;b=6
a=9;b=6*/

其中dw作为一个实际参数传入swap函数,其实是采用值传递的方式。复制了dw的副本传入swap,而dw只是一个引用变量,而并没有复制实际对象。所以传入之后相当于在main栈中有一个dw指向实际对象,同时在swap栈中也有一个dw指向实际对象。所以在swap函数中操作的是实际对象,而并非副本。

形参个数可变的方法:

JDK1.5之后,java允许定义形参个数可变的参数,从而允许为方法指定数量不确定的形参。

实例如下:

package org.westos.practice;

public class Varages {
    public static void test(int a,String... books){
        //books被当做数组处理
        for (String tmp:books){
            System.out.println(tmp);
        }
        //输出整形变量a的值
        System.out.println(a);
    }

    public static void main(String[] args) {
        test(5,"Java","c++","python");
    }
}

/*Java
c++
python
5*/

可以看出形参个数可变的参数本质就是一个数组参数

public static void test(int a,String... books)
public static void test(int a,String[] books)

这两段代码效果完全一样,但是调用的时候存在差别,形参个数可变的这种方法调用更加简洁。但是它只能放在形参最后传入,而数组可以放在任意位置传入。

  • 类名作为形参
    先定义一个类,在测试类中再定义一个需要类传入的方法;

Animal.class

package org.westos.practice;

public class Animal {

    public void eat(){
        System.out.println("我是普通类的方法");
    }
}
  • 抽象类作为形参
    同上

AbsAnimal.class

package org.westos.practice;

public abstract class AbsAnimal {

    public abstract void show();
}

Cat类实现该抽象类;
Cat.class

package org.westos.practice;

public class Cat  extends AbsAnimal{
    @Override
    public void show() {
        System.out.println("我是抽象类子类的重写方法");
    }
}
  • 接口类作为参数传递

MyInterface.class

package org.westos.practice;

public interface MyInterface {
    void intershow();
}

Dog类实现该抽象类;
Dog.class

package org.westos.practice;

public class Dog implements MyInterface {
    @Override
    public void intershow() {
        System.out.println("我是接口子类实现的方法");
    }
}

测试类中:

package org.westos.practice;

public class MyTest {
    public static void main(String[] args) {

        //如果方法需要传入一个类,你就传入这个类的对象
        methodClass(new Animal());

        //如果方法需要传入一个抽象类,你就传入这个抽象类子类的对象
        //Cat类实现了抽象类的方法
        //AbsAnimal absan= new Cat();
        methodAbsClass(new Cat());

        //如果方法需要传入一个接口类,你就传入这个接口类实现的子类对象
        //Dog类实现了接口方法
        methodInterClass(new Dog());
    }

    public static void methodClass(Animal an){
        an.eat();
    }

    public static void methodAbsClass(AbsAnimal absan){
        absan.show();
    }

    public static void methodInterClass(MyInterface inface){
        inface.intershow();
    }
}

成员变量和局部变量

注意事项:

  1. 成员变量又可分为类变量(被static修饰)和实例变量(没有被static修饰)。
    类变量随着类的创建而创建,销毁而销毁;这个类普遍相同的属性,如人都有两个眼睛,一个嘴巴。
    实例变量随着对象的创建而创建,销毁而销毁,对于同一个类,不同对象属性不同,如每个人的身高体重。
  2. 在一个方法中同名的局部变量会覆盖成员变量,不过可以通过this或指定类名作为调用者来访问被覆盖的成员变量。不过大部分时候应该避免这种重名情况。
  3. 在程序中使用局部变量,应该尽可能的缩小局部变量的范围,局部变量的作用范围越小,它在内存中停留的时间就越短,程序运行性能就越好。

深入构造器

构造器是一个特殊的方法,这个方法用于创建实例时执行初始化。构造器是创建对象的重要途径。

使用构造器执行初始化

当创建一个对象时系统为这个对象的实例变量进行默认初始化,这种默认的初始化把所有基本类型的实例变量设为0或false。把所有引用类型的实例变量设为null。如果想改变这种默认的初始化,想让系统创建对象时就为该对象的实例变量显式指定初始值,就可以通过构造器来实现。

注意:如果程序员没有为java提供任何构造器,则系统会为这个类提供一个无参数的构造器,这个构造器为空,不做任何事,但无论如何如何java类至少包含一个构造器。

package org.westos.practice1;

public class ConstructorTest {
    public String name;
    public int count;

    //提供自定义的构造器,该构造器包含两个参数
    public ConstructorTest(String name,int count){
        //构造器里的tjis代表它进行初始化的对象
        //将传入的两个参数赋值给this代表对象的name和count
        this.name=name;
        this.count=count;
    }

    public static void main(String[] args){
        //系统将会对该对象执行自定义的初始化
        ConstructorTest tc=new ConstructorTest("java",3);

        System.out.println(tc.name);
        System.out.println(tc.count);
    }
}

注意:虽然说构造器是创建对象的途径,但实际上当程序员调用构造器的时候,系统先为该对象分配内存空间,并为这个对象执行默认初始化,这个对象已经产生了,这些操作在构造器执行之前就都完成了。也就是说,当系统开始执行构造器之前,系统已经创建了一个对象,只是这个对象还不能被外部程序访问,只能在该构造器中用this来引用。当构造器执行完之后,这个对象会作为构造起的返回值被返回,通常会赋给另一个引用变量,从而让外部程序可以访问该对象。

通常把构造器设置成public访问权限,从而允许系统中的任何位置的类都能创建该类的对象。

构造器重载

构造器重载和之前的方法重载一样,每个重载的构造器使用与类相同的名字。只是需要传入的参数个数和类型不一样;

实例如下:

package org.westos.practice1;

public class Constructer {
    String name;
    int age;
    
    //默认的构造器,由于还要定义其他重载构造器,所以得让他显式,而不被覆盖
    public Constructer(){
        
    }
    public  Constructer(String name){
        this.name=name;
    }
    public  Constructer(int age){
        this.age=age;
    }
    public static void main(String[] args) {

        Constructer ct=new Constructer();
        System.out.println(ct.name);
        System.out.println(ct.age);
/*null
0*/
        String name="Liming";
        Constructer ct1=new Constructer(name);
        System.out.println(ct1.name);
        System.out.println(ct1.age);
/*Liming
0*/
        int age=4;
        Constructer ct2=new Constructer(age);
        System.out.println(ct2.name);
        System.out.println(ct2.age);
/*null
4*/
    }
}

本例使用方法重载一共创建了三个对象。

 

 

 

 

 

 

 

 

 

猜你喜欢

转载自blog.csdn.net/weixin_43917654/article/details/86072352