【JAVA基础】函数知识

1.函数参数传递方式

虽然java通过引用操作对象,所有的对象变量都是引用,然而,java不能通过引用传递方法参数,它通过值传递。基本类型传递的是值的副本,引用类型传递的是引用的副本。如果函数内修改了该参数,仅改变副本,而原始值保持不变

public void tricky(Point arg1, Point arg2)
{
  arg1.x = 100;
  arg1.y = 100;
  //交换
  Point temp = arg1;
  arg1 = arg2;
  arg2 = temp;
}
public static void main(String [] args)
{
  Point pnt1 = new Point(0,0);
  Point pnt2 = new Point(0,0);
  System.out.println("X: " + pnt1.x + " Y: " +pnt1.y); 
  System.out.println("X: " + pnt2.x + " Y: " +pnt2.y);
  System.out.println(" ");
  tricky(pnt1,pnt2);
  System.out.println("X: " + pnt1.x + " Y:" + pnt1.y); 
  System.out.println("X: " + pnt2.x + " Y: " +pnt2.y);  
}
//输出结果
X: 0 Y: 0
X: 0 Y: 0
X: 100 Y: 100
X: 0 Y: 0

即使该方法是值传递,但它还是成功的输出了pnt1的值。然而,pnt1和pnt2的却没有交换成功。这两个参数引用传递给方法时事实上是把原始引用复制了一份。函数方法内的交换只是复制引用地址的交换,原始引用并没有发生变化。传给方法后,一个对象至少有两个引用。在函数方法里面可以修改对象的数据

image.png

2.实现函数参数的“任意化”的手段

可以通过Object和泛型实现参数的“任意化”,相比较的优缺点:

  • Object要做显式的强制类型转换,而这种转换是要求开发者对实际参数类型可以预知的情况下进行的。而泛型的好处是在编译的时候检查类型安全,并且所有的强制转换都是自动和隐式的,提高代码的重用率。
  • 从安全的角度来看,由程序员自己强制类型转换,出错率很高。采用范型后由编译器生成强制类型转换的代码,降低了出错率。JDK1.5以后就有了泛型。

3.动态参数

4.函数方法使用final 修饰参数的作用。

参数(如果是引用类型,引用类型参数是所指的引用副本)不能被重新赋值,否则编译就通不过。是否使用final修饰参数,对外部的影响实际效果是一样的
如果函数方法里面使用匿名内部类,并且内部类中使用该参数。那么参数必须用final修饰。局部内部类(包括匿名局部内部类和普通内部类)中使用局部变量,那么这个局部变量必须使用final修饰。如:

public class Outer {
    {
       //x和y必须用final修饰,否则编译不通过
        final int x=100;
        final int y=100;
       //内部类
        class BlockInner{
            int z=100;
            public int addXYZ(){return x+y+z;}
        }
        BlockInner bi=new BlockInner();
        num=bi.addXYZ();
    }
    private int num;
}

用final修饰是因为:
(1)对于普通局部变量他的作用域就是该方法内,当方法结束该局部变量就随之消失;但局部内部类可能产生隐式的“闭包”,闭包将使得局部变量脱离他所在的方法继续存在。此时就会出现一种情况,就是内部类要访问一个不存在的局部变量。如下面代码:

//name 必须使用final修饰,否则编译不通过
public void mRun(final String name){
new Runnable() {
public void run() {
       try {
            Thread.sleep(3000);
       } catch (InterruptedException e) {
         e.printStackTrace();
       }  
       System.out.println(name);
}
}.start();
}
//方法myRun已调用结束(局部变量已死亡),但是匿名内部类(线程)对象仍然活着,需要使用外部局部变量name。

(2)上面代码说明局部类的对象生命期会超过局部变量,解决这一问题的办法就是使用final修饰局部变量,使内部类扩大局部变量的作用域。其原理通过将final局部变量"复制"一份, 复制品直接作为方法内部类中的数据成员,方法内部类访问的其实是这个局部变量的复制品!而且,由于被final修饰的变量赋值后不能再修改,所以就保证了复制品与原始变量的一致
注:JDK1.8版本以后,可以不用final修饰,都是隐式处理的。但是本质上该变量还是final的。这该版本的新特性。

你可能感兴趣的:(【JAVA基础】函数知识)