Thinking in java note1

Part information collecting from http://blog.csdn.net/leonliu06/article/details/78638841

1. 如果已经定义了一个构造器(无论是否有参数),编译器就不会帮你自动创建默认构造器

2. a.peel(1) 等于 Banana.peel(a, 1), 在peel方法内部 a就是this

3. 当发生“垃圾回收”时,finalize()才得到调用, Java里的对象并非总是被垃圾回收(因为Java的“垃圾回收”并不能保证一定会发生, 只要程序没有濒临存储空间用完的那一刻,垃圾回收可能就会一直没有发生)

4. 自适应的,分代的,停止-复制,标记-清扫式垃圾回收器

5.对于方法的局部变量,如果使用前没有初始化,Java以编译时错误(注意,如果方法内的局部变量未被使用,将不会编译错误)的形式来贯彻这种保证。   对于类的成员变量:  •成员变量是基本类型,Java会自动初始化初值0;  •成员变量是引用类型,Java会自动初始化初值null;  •无法阻止自动初始化的进行,它将在构造器被调用之前发生,如下,i首先会被置0,然后变成7。   6. 先初始化构造器之外的成员,再初始化构造器里面的

7. 静态初始化至于在必要时刻才会进行,在对象第一次被创建或者第一次访问静态数据。顺序,先静态对象,后非静态对象 

8. Java解释器的运行过程:

首先,找出环境变量CLASSPATH,用作查找.class文件的根目录。 然后,从根目录开始,解释器获取包的名称并将句点替换成反斜杠(于是,package net.mrliuli.training 就变为 net\mrliuli\training 或 net/mrluli/training 或其他,这一切取决于操作系统)以从CLASSPATH根中获取一个相对路径。 将CLASSPATH根目录与上面获取的相对路径相连接得到一个绝对路径,用来查找.class文件。

9.private:可以定义方法,属性,定义的方法和属性不能被类的外部所看到。

default:可以在本包的任意地方访问。

public:都可以访问,不受任何限制。

protected:保护,同一包中的类可以访问。不同包的非子类不可以访问。

10. static final STATIC_FINAL 占据一段不能改变的存储空间,声明的时候就为其显式地赋值,否则编译时不通过

ConstantValue属性的作用是通知虚拟机自动为静态变量赋值,只有被static修饰的变量才可以使用这项属性。非static类型的变量的赋值是在实例构造器方法中进行的;tatic类型变量赋值分两种,在类构造其中赋值,或使用ConstantValue属性赋值。

在实际的程序中,只有同时被final和static修饰的字段才有ConstantValue属性,且限于基本类型和String。编译时Javac将会为该常量生成ConstantValue属性,在类加载的准备阶段虚拟机便会根据ConstantValue为常量设置相应的值,如果该变量没有被final修饰,或者并非基本类型及字符串,则选择在类构造器中进行初始化。

•static修饰的字段在加载过程中准备阶段被初始化,但是这个阶段只会赋值一个默认的值(0或者null而并非定义变量设置的值)初始化阶段在类构造器中才会赋值为变量定义的值。 •final修饰的字段在运行时被初始化,可以直接赋值,也可以在实例构造器中赋值,赋值后不可修改。 •static final修饰的字段在javac编译时生成comstantValue属性,在类加载的准备阶段直接把constantValue的值赋给该字段。 可以理解为在编译期即把结果放入了常量池中。

final 基本类型数据 基本类型变量应用final关键字时,将向编译器告之此变量是恒定不变的,即它是编译期常量。这样编译器可在编译时执行计算式,从而减轻了运行时负担(提高效率)。编译期常量在定义(声明)时必须对其赋值(声明时也可以不赋(此时叫空白final),但必须在构造器中赋值,所以final域在使用前总是被初始化。)。final常量常与static一起使用,强调只有一份。编译期常量(带有恒定初始值),即 static final 的基本类型变量全用大写字母命名,并且字与字之间用下划线隔开(这就像C常量一样,C常量是这一命名传统的发源地)

final 对象引用 用于对象引用,则引用恒定不变,即一旦引用初始化指向一个对象,就无法再把它改变为指向另一个引用,但对象其自身是可以被修改的。这种情形同样适用数组,因为如前面所述,Java数组也可(看作)是引用。

final参数 指明为final的方法参数,意味着方法内只能读而不能修改参数,这一特性主要用来向匿名内部类传递数据。

final方法 使用final方法的原因有两个: 锁定方法,以防任何继承类修改它的含义。这是出于设计的考虑。 效率。在Java早期版本中,方法声明为final,就是同意编译器针对该方法的所有调用都转为内嵌调用。而在Java SE5/6时,应该让编译器和JVM云处理效率问题,只有在想要明确禁止覆盖时,才将方法设置为final的。

final和private关键字 类中所有的private方法都隐式地指定为是final的。由于无法取用private方法,所以也就无法覆盖它。 派生类中试图“覆盖”父类中一个private方法(隐含是final的),似乎奏效,编译器不会出错,但实际上只是在派生类中生成了一个新的方法,此时并没有覆盖父类的private方法。

final类 final类表明对该类的设计永不需要变动,或者出于安全的考虑,你不希望它有子类。因为final类禁止继承,所以final类中所有的方法都隐式指定为是final的,因为无法覆盖它们。在final类中可以给方法添加final修饰词,但这不会增添任何意义。

11.初始化及类的加载

类的加载 https://blog.csdn.net/alinyua/article/details/79908006

  Java采用了一种不同的对类加载的方式,Java每个类的编译代码都存在于它自己的独立的文件中(.class文件)。该文件只在其代码需要被使用时才会被加载(That file isn’t loaded until the code is needed)。通常,可以说“类的代码在初次使用时才加载。”这通常是指加载发生于构造类的第一个对象之时,但是当访问static域或static方法时,也会发生加载。(构造器也是static方法,尽管static关键字并没有地写出来。因此更准确地讲,++类是在其任何static成员被访问时加载的++。) 依次初始化基类的static,然后导出类的static。加载完毕后,对象可以被创建了。首先,对象中所有的基本类型都会被设置默认值,引用设置null。

只有当对类的主动使用的时候才会导致类的初始化,类的主动使用包括以下六种: 1.创建类的实例,也就是new的方式(字节码指令:new) 2.读取或设置某个类或接口的静态变量(被final修饰,在编译期已经把结果放入常量池的静态字段除外)(字节码指令:getstatic,putstatic) 3.调用类的静态方法(字节码指令:invokestatic) 4.反射(如Class.forName(“com.shengsiyuan.Test”)) 5.初始化某个类的子类,则其父类也会被初始化 6.Java虚拟机启动时被标明为启动类的类(Java Test,包含main()的类),直接使用java.exe命令来运行某个主类

调用static final修饰的常量不会导致类加载

类加载有三种方式: 1.命令行启动应用时候由JVM初始化加载 2.通过Class.forName()方法动态加载 3.通过ClassLoader.loadClass()方法动态加载

1.Class.forName():将类的.class文件加载到jvm中之外,还会对类进行解释,执行类中的static块; 2.ClassLoader.loadClass():只干一件事情,就是将.class文件加载到jvm中,不会执行static中的内容,只有在newInstance才会去执行static块。 3.Class.forName(name, initialize, loader)带参函数也可控制是否加载static块。并且只有调用了newInstance()方法采用调用构造函数,创建类的对象 //使用Class.forName()来加载类,并指定ClassLoader,初始化时不执行静态块

双亲委派模型的工作流程

如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把请求委托给父加载器去完成,依次向上,因此,所有的类加载请求最终都应该被传递到顶层的启动类加载器中,只有当父加载器在它的搜索范围中没有找到所需的类时,即无法完成该加载,子加载器才会尝试自己去加载该类。

双亲委派机制: 1.当AppClassLoader加载一个class时,它首先不会自己去尝试加载这个类,而是把类加载请求委派给父类加载器ExtClassLoader去完成。 2.当ExtClassLoader加载一个class时,它首先也不会自己去尝试加载这个类,而是把类加载请求委派给BootStrapClassLoader“`去完成。 3.如果BootStrapClassLoader加载失败(例如在$JAVA_HOME/jre/lib里未查找到该class),会使用ExtClassLoader来尝试加载; 4.若ExtClassLoader也加载失败,则会使用AppClassLoader来加载,如果AppClassLoader也加载失败,则会报出异常ClassNotFoundException

初始化 初次使用之处也是staic初始化发生之处。所有的static对象和static代码段都会在加载时依程序中的顺序(即,定义类时的书写顺序)而依次初始化。当然,定义为static的东西只会被初始化一次。

12. 静态绑定:即前期绑定。在程序执行前方法已经被绑定,此时由编译器或其它连接程序实现。针对java,简单的可以理解为程序编译期的绑定。java当中的方法只有final,static,private和构造方法是前期绑定的。 动态绑定:即晚期绑定,也叫运行时绑定。在运行时根据具体对象的类型进行绑定。在java中,几乎所有的方法都是后期绑定的

13. 常量池 https://blog.csdn.net/vegetable_bird_001/article/details/51278339

14. 抽象方法 abstract void f() 在class前添加abstract关键字,定义成抽象类。 •抽象类不能实例化,即不能通过new生成对象,但注意可以追加{}生成匿名实现类,仍然不是它自己的实例化。 •抽象类可以有构造函数,但不能直接调用,通常由实现类构造函数调用。 •抽象类的方法前添加abstract关键字,定义抽象方法,相当于C++的纯虚函数,派生类必须重写该方法,然后才能实例化。Java类中如有抽象方法,则类符号前必须也要添加abstract关键字,定义为抽象类(可以没有抽象方法)。 •抽象类中可以没有抽象方法,即可以全部是含方法体的非抽象方法。

•接口可以包含域,且隐式地是static 和 final的,显然,接口中的域不能是空final,这些域不是接口的一部分,它们存储在该 接口的静态存储区域内。 •接口关键字interface前可以添加public修饰符,不加默认是包访问权限,接口的方法默认都是public的。

15. 链接到外部类(Java非static的普通内部类自动拥有对其外围类所有成员的访问权)。

  Java普通内部类能访问其外围对象(enclosing object)的所有成员,而不需要任何特殊条件 。在Java中,当某个类创建一个内部类对象时,此内部类对象必定会秘密地捕获一个指向那个外围类的对象的引用。然后,在你访问此外围类的成员时,就是用那个引用来选择外围类的成员。这些细节是由编译器处理的。Java的迭代器复用了这个特性。

内部类声明为static时,不再包含外围对象的引用.this,称为嵌套类。 - 创建嵌套类,不需要外围对象。 - 不能从嵌套类的对象中访问非静态的外围对象。

•Java非static的普通内部类可应用.this返回其外围对象的引用。 •外围对象可应用.new来生成一个内部类对象。 dn.new Inner()

内部类使得多重继承的解决方案变得完整

16. Iterator迭代器使得客户端程序员不必知道或关心容器类的底层结构。 •ListIterator只能用于各种List类的访问。ListIterator可以双向移动,而Iteraotr只能向前移动。

猜你喜欢

转载自www.cnblogs.com/marcocao/p/9933248.html
今日推荐