FKJAVA读书笔记--第六章--面向对象(下)

1.Java1.7版本以上优化了包装类,提供了compare比较方法。并且布尔值得比较,truefalse大。

 

2.java中所有的对象都可以和字符串进行运算,当java对象和字符串进行运算时,会自动调用对象的toString方法返回值和字符串进行运算。Object类的toString方法总是默认返回类名+@+hashcode值。

 

3.使用==,如果两个变量都是基本类型变量,并且都是数值类型(都数值类型没有严格要求),只要这两个变量的值相等

 如果两个变量时引用类型变量,则必须要这两个引用类型变量都指向同一个对象时,才会返回true

 

4.String str4=new String("疯狂java");

 String str1="疯狂java";

 System.out.println("11=>"+(str1==str4));===false

 System.out.println("33=>"+str1.equals(str4));===true

 对于引用类型==   true必须是指向同一个对象

String类重写了Objectequals方法,只要两个字符串包含的字符序列相同,即会返回true

但是其他的object中的equals还是原生的objectequals方法,其实还是==判断。

 

5.equals方法中不要用instanceOf方法,因为可以出现父类子类的情况,这时候instance也是返回true,但是equals要求的必须是两个对象是完完全全的同一个类。需要直接判断类的class name

 

6.单例模式


package com.gu.test;

public class SingleInstanceTest
{
    private volatile static SingleInstanceTest single;

    private SingleInstanceTest()
    {

    }

    /**
     * @return  
     * @Description:双重检查锁定 才能达到真正的单列效果
     */
    public static SingleInstanceTest getSingle()
    {
        if(single == null)
        {
            synchronized(SingleInstanceTest.class)
            {
                if(single == null)
                {
                    single = new SingleInstanceTest();
                }
            }
        }
        return single;

    }

    public static void main(String[] args)
    {
        SingleInstanceTest test = SingleInstanceTest.getSingle();
        SingleInstanceTest test2 = SingleInstanceTest.getSingle();
        System.out.println(test == test2);
    }
}

 

7.final关键字   并不是说final修饰的变量不能赋值,而是final一旦获得了初始值,该final变量的值就不能被重新赋值。

 Java规定final修饰的成员变量必须由程序员显式的指定初始值

 Javafinal局部变量,也是必须由程序员显式的指定初始值,但是可以在声明的时候初始化,也可以在后面初始化唯一的一次;final的形参不能被赋值

 

8.final修饰引用类型和基本类型的区别:

 引用类型,只要保证那个引用类型变量不变,其引用的对象可以改变

 基本类型,要保证那个值一直不能变。

 

9.对一个final修饰的变量而言,无论他是类Field,实例Field,还是局部变量,只要满足:

 使用final修饰;在定义该final变量时指定了初始值;该初始值可以在编译时就被确定下来==》这个final变量就不在是一个变量,而是一个直接量。

 

10.对于final修饰的变量,只有在定义时就确定了值才可以被当成宏变量。

 Final String s=”sss”+String.valueOf(2115);===>这个就不能被当做宏变量。这个必须在运行时候才能被定下来。

 

11.final修饰的方法仅仅是不能被重写,但是可以被重载(方法的参数形式不一样但方法名相同)。

 

12.final修饰的类不可以有子类   类如java.lang.Math

 

13.如果要设计一个不可变类,一定要注意它的引用field

 

14.不可变类的实例状态不可变,可以很方便的被多个对象共享。如果程序会经常使用一个不可变类的实例,则需要对其进行缓存处理。

当系统会重复使用一个对象的时候,可以采用缓存的机制,但是不能盲目的使用缓存

 

15.不可变类,并不是那个对象的field只能是一个值,而是当这个不可变类被实例出来之后,其field只能被初始化一次

 

16.Integer只会缓存-128127的数,IntegervalueOf方法采用了缓存机制

 

17.如何让一个子类包含一个方法,又不要父类对这个方法有一个明确的实现==》抽象类

 抽象方法只有方法的签名,没有方法的具体实现 ,有抽象方法的类必须为抽象类,但是抽象类可以没有抽象方法

 

18.抽象类不能被实例化。所以抽象类的构造器只是用于被子类调用

抽象类可以用“有得有失”四个字来形容==》得,使类有了多了一个能力,可以包含抽象方法  失,抽象类无法被实例化 

 

19.抽象类的好处,避免了在多态执行时候,调用一个方法必须要进行强制类型转换的情况。

 Final表示类不可以被继承,而abstract表示一个类必须要被继承。因此两者无法共存。 

Static修饰的部分属于类,因此不能用staticabstract共存

Private表示了一个方法体将不被外界访问,而abstract修饰的方法必须要被访问的,因此privateabstract也不能访问。

 

20.更加彻底的抽象=》接口  接口只能继承接口,不能继承类  接口中的方法只能是抽象方法,系统会自动为其填补上abstract关键字

 

21.接口里的常量field,系统会自动为他们加上staticfinal,接口没有构造器和初始化块,因此接口里定义的field必须在定义时指定默认值

 

22.接口内定义的内部类、接口、枚举类、默认都采用public static修饰符,不管定义时是否指定这两个修饰符,系统都会自动使用public static 对他们进行修饰。

 

23.某种角度接口可以被看成是特殊的类,跟类文件名的定义一样,一旦一个类文件中有一个public接口,那么就不能有第二个了,并且文件名要和这个一样。

 

24.接口支持多继承,子接口扩展某个父接口,那么父接口中的所有抽象方法、field、内部类、枚举类定义都会被获得。实现接口的方法时,必须使用public关键字(子类的访问权限要比父类大或者相同)

 

25.接口和抽象类的区别之处:

 接口体现的是一种规范。接口弥补了java单继承的不足之处。

 抽象则是体现了一种模板式设计。

26.非静态内部类的实例必须寄存在外部类的实例中,者就是为什么在非静态内部类里面可以直接调用外部类field的原因。

 

27.static不可以修饰外部类,但可以修饰内部类,使内部类由与外部类实例相关变成与外部类类相关。

 

28.非静态内部类的子类不一定是内部类。但是一个原则必须要坚持,那就是一个内部类的子类的对象存在,则必须由一个外部类的对象存在。当程序需要使用内部类的时候,应该优先使用静态内部类。  内部类也不可以在外部类子类中重写。

 

29.局部内部类,不论是局部变量还是局部内部类它的上一级程序单元都是方法。(因此没有必要使用static修饰符),又因为一个方法中的局部变量或者局部内部类不能被另一个方法看到(因此访问控制符也没有任何意义了)。

局部内部类的class文件格式:OuterClass$NInnerClass.class   多了个N。。用于区分万一类名相同的局部内部类。

 

30.匿名内部类:匿名内部类必须继承一个父类,或者实现一个接口,但最多只能一个。

  规则:1.匿名内部类不允许是抽象类,抽象类不好直接创建对象。

        2.匿名内部类不能定义构造器,因为匿名内部类没有方法名。但是匿名内部类可以定义初始化模块进行初始化工作。

  匿名内部类只会使用一次,所以在那些只要使用一次的地方可以考虑使用匿名内部类。

  如果匿名内部类(或者局部内部类)要访问外部类的局部变量,则那个局部变量必须要用final关键字修饰。

  因为如果不用final,那个局部变量的生命周期只属于这个方法,但是匿名内部类却不是这样的生命周期,不用final会出现,到时候会出现内部类想用一个变量,结果内存中没有!

 

31.闭包和回调:

  回调就是某一个方法获得了内部类对象的引用之后,就可以在合适的时候反过来调用外部类实例的方法。


package com.gu.test;


interface CallBack
{
    public void doCURD();
}

class A implements CallBack
{

    private B b;

    public A()
    {
       
    }

    public A(B b)
    {
        this.b = b;
    }

    public void add()
    {
        b.execute(new A());//YOU CALL ME
    }

    @Override
    public void doCURD()
    {
        System.out.println("doCURD...");
    }

}

class B
{
    public void execute(CallBack back)
    {
        getDBConnection();
        back.doCURD();//ME CALL YOU
        releaseDBConnection();
    }

    public void getDBConnection()
    {
        System.out.println("getConnection...");
    }

    public void releaseDBConnection()
    {
        System.out.println("releaseConnection...");
    }
}

public class CallBackTest
{
    public static void main(String[] args)
    {
        B b=new B();
        new A(b).add();
    }
}

 

32.枚举类:一个类的对象有限并且固定,则可以称之为枚举类。

l 枚举类用enum关键字,并且枚举类继承自java.lang.Enum类 Enum类实现了SerializableCompareable

l 使用enum定义、非抽象的枚举类默认使用final关键字修饰,因此枚举类不能派生子类

     这里并不是所有的枚举类都使用了final修饰符,对于一个抽象的枚举类(包含抽象的方法),系统会默认使用abstract修饰符

l 枚举类的构造器只能使用private修饰符

l 枚举类所有的实例必须在第一行列出,系统默认会加上finalstatic关键字修饰

 

33.通过EnumvalueOf方法获取指定枚举类的枚举值

 Public static >T valueOf(Class enumType,String name)

 

34.枚举类也可以实现一个或者多个接口与普通类一样

 

35枚举类需要显式的创建枚举值

 

36.对象在内存中的三种状态:

l 可达状态:对象创建好之后,程序可通过引用变量调用该对象的field和方法

l 可恢复状态:如果一个程序中某个对象不再有任何引用变量引用它,它就进入了可达状态。系统会调用finalize()方法,使一个引用变量重新引用这个对象。

l 不可达状态: 当对象与所有的引用变量切断了联系,并且系统调用了finalize()方法依然没有使该对象变成可达,那么它就永久变成了不可达状态。这是垃圾回收机制将起作用

 

37.强制垃圾回收:

 System.gc();

 Runtime.getRuntime().gc();

 

38.java一共有四种引用类型:(强软弱虚

① 强引用:StrongReference 

程序创建一个对象并复制给一个引用变量,程序通过引用变量来操作实际的对象。

② 软引用:SoftReference  1

当一个对象只有软引用时,它有可能被垃圾回收机制回收。软引用只用于对内存敏感的应用。

③ 弱引用:WeakReference   2

弱引用和软引用很像,但是弱引用的级别更低,弱引用即使内存足够,只要垃圾回收机制运行,就会被回收。

④ 虚引用:PhtantomReference   3

虚引用类似于完全没有引用,虚引用对对象本身没有太大的影响,对象甚至感觉不到虚引用的存在。虚引用主要用于跟踪对象被垃圾回收的状态,虚引用不能单独使用,虚引用必须和引用队列referencequeue联合使用。

上面三个引用类都有一个get方法,用于获取他们所有的引用对象

 

39.软引用,弱引用和引用队列一起使用时,系统在回收被引用的对象之后,将会把它添加到关联的引用队列中。与前面不同的是,虚引用在回收之前会把对应虚引用添加到队列,这样我们就可以在它被回收之前,做一些处理操作。

 

40.String str=new String("顾学武");

 String str="顾学武";

 第一种将采用实例出新的对象方式,第二种实际上用的是常量池。

 

41.系统无法通过虚引用获取到被引用的对象。

 

42.为什么要使用这些引用类型:可以有效避免对象被遗留在内存中。可以减少在程序生命周期中内存的消耗。

43.如何从这些引用中重新取出之前的对象?

 

   private static WeakReference wr;

   public Object reGetIt()

    {

        if(wr.get() != null)

        {

            return wr.get();

        }

        else

        {

            Object obj = new String("顾学武");

            wr = new WeakReference((String) obj);

            return obj;

        }

}

 

  

 

你可能感兴趣的:(Java)