java编程思想学习笔记(二)

Access Control

Since the default constructor is the only one defined and it’s private, it will prevent inheritance of this class.

 

It is possible, though not typical, to have a compilation unit with no public class at all. In this case, you can name the file whatever you like(although naming it arbitrarily will be confusing to people reading and maintaining the code).

 

If you don’t want anyone else to have access to that class, you can make all the constructors private, thereby preventing anyone but you, inside a static member of the class, from creating an object of that class.

 

Reusing Class

There are many cases in which the cleanup issue is not a problem; you just let the garbage collector do the work. But when you must perform explicit cleanup, diligence and attention are required, because there’s not much you can rely on when it comes to garbage collection. The garbage collector might never be called. If it is, it can reclaim objects in any order it wants. You can’t rely on garbage collection for anything but memory reclamation. If you want cleanup to take place, make your own cleanup methods and don’t use finalize().

 

Although inheritance gets a lot of emphasis when teaching OOP, it doesn’t mean that you should use it everywhere you possibly can. On the contrary, you should use it sparingly, only when it’s clear that inheritance is useful. One of the clearest ways to determine whether you should use composition or inheritance is to ask whether you should use composition or inheritance is to ask whether you’ll ever need to upcast from your new class to the base class. If you must upcast, then inheritance is necessary, but if you don’t need to upcast, then you should look closely at whether you need inheritance.

 

Java’s final keyword has slightly different meanings depending on the context, but in general it says, “This cannot be changed.” You might want to prevent changes for two reasons: design or efficiency. Because these two reasons are quite different, it’s possible to misuse the final keyword.

 

Many programming languages have a way to tell the compiler that a piece of data is “constant.” A constant is useful for two reasons:

1.       It can be a compile-time constant that won’t ever change.

2.       It can be a value initialized at run time that you don’t want changed.

In the case of a compile-time constant, the compiler is allowed to “fold” the constant value into any calculations in which it’s used; that is, the calculation can be performed at compile time, eliminating some runtime overhead. In Java, these sorts of constants must be primitives and are expressed with the final keyword. A value must be given at the time of definition of such a constant.

A field that is both static and final has only one piece of storage that cannot be changed.

When final is used with object references rather than primitives, the meaning can be confusing. With a primitive, final makes the value a constant, but with an object reference, final makes the reference a constant. Once the reference is initialized to an object, it can never be changed to point to another object. However, the object itself can be modified; Java does not provide a way to make any arbitrary object a constant. (You can ,however, write your class so that objects have the effect of being constant.) This restriction includes arrays, which are also objects.

 

class Value{

    int i;

    public Value(int i){

       this.i=i;

    }

}

public class FinalData {

    private static Random rand=new Random(47);

    private String id;

    public FinalData(String id){

       this.id=id;

    }

    //Can be compile-time constants:

    private final int valueOne=9;

    private static final int VALUE_TWO=99;

    //Typical public constant:

    public static final int VALUE_THREE=39;

    //Cannot be compile-time constants:

    private final int i4=rand.nextInt(20);

    static final int INT_5=rand.nextInt(20);

    private Value v1=new Value(11);

    private final Value v2=new Value(22);

    private static final Value VAL_3=new Value(33);

    //Arrays:

    private final int[] a={1,2,3,4,5,6};

    public String toString(){

       return id+": "+"i4= "+i4+". INT_5 = "+ INT_5;

    }

    public static void main(String[] args) {

       FinalData fd1=new FinalData("fd1");

//     !fd1.valueOne++; //Error: can't change value

       fd1.v2.i++;// Object isn't constant!

       fd1.v1=new Value(9);//OK -- not final

       for(int i=0;i<fd1.a.length;i++){

           fd1.a[i]++;//Object isn't constant!

//         fd1.a=new int[3];

       }

       System.out.println(fd1);

       System.out.println("Creating new FinalData");

       FinalData fd2=new FinalData("fd2");

       System.out.println(fd1);

       System.out.println(fd2);

    }

}

Just because something is final doesn’t mean that its value is known at compile time. This is demonstrated by initializing i4 and INT_5 at run time using randomly generated numbers. This portion of the example also shows the difference between making a final value static or non-static. This difference shows up only when the values are treated the same by the compiler. (And presumably optimized out of existence) The difference is shown when you run the program. Not that the values of i4 for fd1 and fd2 are unique, but the value for INT_5 is not changed by creating the second FinalData object. That’s because it’s static and is initialized once upon loading and not each time a new object is created.

 

Java allows the creation of blank finals, which are fields that are declared as final but are not given an initialization value. In all cases, the blank final must be initialized before it is used, and the compiler ensures this. However the blank finals provide much more flexibility in the use of the final keyword since, for example, a final field inside a class can now be different for each object, and yet retain its immutable quality.

 

public class BlankFinal {

 

    private final int i=0;

    private final int j;

    private final Poppet p;

   

    public BlankFinal(int j1,Poppet p1){

       j=j1;

       p=p1;

    }

}

 

class Poppet{

    private int i;

    Poppet(int ii){

       i=ii;

    }

}

You’re forced to perform assignments to finals either with an expression at the point of definition of the field or in every constructor. That way it’s guaranteed that the final field is always initialized before use.

 

final arguments:

public class FinalArguments {

 

    void with(final Gizmo g){

//     g=new Gizmo(); Illeganl -- g is final

    }

   

    void without(Gizmo g){

       g=new Gizmo();// OK  -- g not final

       g.spin();

    }

    void f(final int i){

//     i++; Can't change , You can only read from a final primitive;

    }

    int g(final int i){

       return i+1;

    }

 

}

 

class Gizmo{

    public void spin(){}

}

 

There are two reasons for final methods. The first is to put a “lock” on the method to prevent any inheriting class from changing its meaning. This is done for design reasons when you want to make sure that a method’s behavior is retained during inheritance and cannot be overridden.

The second reason final methods have been suggested in the past is efficiency. In more recent versions of Java, the virtual machine( in particular, the hotspot technologies) can detect these situations and optimize away the extra indirection, so it is no longer necessary-in fact, it is now generally discouraged- to use final to try to help the optimizer. With Java SE5/6, you should let the compiler and JVM handle efficiency issues and make a method final only if you want to explicitly prevent overriding.

Any private methods in a class are implicitly final. Because you can’t access a private method, you can’t override it. You can add the final specifier to a private method, but it doesn’t give that method any extra meaning.

 

The point of first use is also where the static initialization takes places. All the static objects and the static code block will be initialized in textual order(that is, the order that you write them down in the class definition) at the point of loading. The statics, of course, are initialized only once.

The constructor is also a static method even though the static keyword is not explicit. So to be precise, a class is first loaded when any one of its static members is accessed.

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值