• Think in Java ---Chapter 5 初始化与清理


    1. 对象调用方法会隐式传递this指针,因此可以在方法内部使用this调用成员方法,也可以省略。参数列表的this会由编译器自动添加,方法内调用同类实例方法也会自动添加。
      2.可以在方法中返回this指针,这样可以使用方法链调用。
      3.传递this指针只在需要的时候,例如A需要一个修饰过的类B对象,则b.process()。在该方法中b把自己传递给另一个工具类c.(this)。
      4.只能在构造方法中调用一次this或者super的构造方法,并且放在第一句。
      5.this还可表示‘本实例’这个概念。
      6.静态static方法和普通成员方法的区别。

    1.finalize方法不保证调用,即只在gc收集该对象时会调用,但是不应该把资源释放的任务放在finalize方法上。即该方法是完全捆绑在gc过程的发生的。如果内存足够大,对象创建的少,则这个方法可能永远不回收。写在方法中的释放语句就不会执行。数据库的链接不释放或者图像不会被擦除。finalize方法是用来释放‘本地方法’(例如调用c或者c++的方法)malloc后忘记delete的内存。在java中释放资源应该放在如finally或者普通方法中。
    2.一条定理: 垃圾回收只与内存有关,垃圾回收只与内存有关,垃圾回收只与内存有关。 看看深入理解java虚拟机。
    3.finalize方法有一种用法,就是在finalize方法中检查对象的状态是否合规,不合规就输出一条信息。即用来检查自定义的对象终结条件。即检查是否当对象释放时某个东西处于什么状态。(需要调用system.gcc出发GC。),如果这种用法需要调用父类的finalize检查,则super.finalize即可。
    4.java的堆分配可以媲美C的堆栈分配,因为java只是单方向移动分配指针。配合垃圾收集算法,建立起近乎无限的内存分配模型。
    5.不适用引用计数是因为防止循环引用从而释放不了对象。java使用从表面的所有引用变量入手,然后是对象的引用成员变量,循环深入,遍历整个可访问的对象网络。
    6.停止-复制 方法,将进程暂停,将内存中一个区的对象移到另一个区,然后修正所有引用变量,比如堆栈和静态存储区(方法区)。完毕后内存空闲区域是连续的。
    7.标记-清理 方法,适合垃圾较少或无垃圾的情况。并行的遍历并标记存活对象,完毕后再一起释放,此时内存空闲区域是不连续的。根据GC的实现这时也可以运行内存整理线程。也需要进程暂停。
    8.对于小对象,实行 复制整理 策略,大对象占用一块的区域(多个小对象的集合)。块不进行复制,而是记录一个代数(generation count),有一个引用则代数增加。
    9.实际上,这两种方式会自适应切换, 即当内存存在许多碎片时会切换到 停止-复制。 若大部分对象都存活,GC收集器效率很低,则切换为标记-清理。
    10.综合上面的,即GC是一个 : 分代的,自适应的,停止-复制,标记-清理的收集器。
    11.HotSpot虚拟机中还有其他的提升性能的技术,例如加载器相关 的JIT即即时编译器的技术,可以把程序全部或部分翻译为本地机器码(本来是JVM的工作)。当需要装载一个类时,编译器会先找到class文件,并读入内存,使用惰性编译,即只在必要时才编译,代码每次被执行时才编译,所以执行的越多,速度越快。避免了全部编译的增加时间花费并且编译后增大的机器码体积(字节码比机器码小)引发页面调度。
    12.从堆中分配的变量初始时是清零的。局部变量不给值不过编译。
    13.如果要为变量赋值,防止前向引用错误。即
    int i = f();
    int j = g(i);
    int f(){reutrn 11;}
    int g(int n){return n10;}
    正确,但是下面错误,因为我的另外一篇博客写了,java的成员变量初始化是按照顺序初始化的。即使在类中定义分散开。
    int j = g(i);
    int i = f();
    int f(){reutrn 11;}
    int g(int n){return n
    10;}

    1. 只要牢记类的初始化顺序,就知道初始化值是不是空值还是有值。
    2. 因为static成员变量分配在静态区,而堆区都是分配时就已经清零的,所以static变量也有默认值。
      16.利用让引用置null,可以测试不同内存区的清理算法和时机。
      17.静态初始化只在必要时进行,即用到这个类的时候才加载(JIT技术),此时在方法区建立class对象,静态数据区。如果类根本不会被使用,JIT也就不会可能装载他的class文件进行编译,因此也就不能被初始化。即使是有main的类,因为要执行main,也要先执行当前类的静态初始化。只要加载到内存方法区了,就不会再执行静态有关的块了。如果代码以后不用这个类,将会被Full GC收集。
      18.根据上面的描述,可以知道构造方法是静态的。
      19.int[] 仅仅是个引用而已。初始化可以使用 int []a={1,2,3,4};java不允许 int[5] 这种声明。
      20.包装类的数组可以使用两种立刻赋值方式:
      Integer [] a = {
      new Integer(5),
      new Integer(6),
      3, //自动装箱,并且那个‘,’可以带上
      }
      Integer [] b = new Integer[]{
      new Integer(5),
      new Integer(6),
      3, //自动装箱,并且那个‘,’可以带上
      }
      21.可以直接把new Object[]{1,2,"a"}作为参数传给方法,此时因为栈上引用的存在不会被GC。
      22.print方法会调用输出对象的toString()方法,如果是基本数据类型会自动装箱。如果没重写该方法则调用Object的原始方法,则会打印类名和对象地址。
      23.参数数量可变的写法: f(Object... args) { for(Object o: args){....}}。f(int... args){ args.getClass();}等等。然后就不用像第21条那样非得传入一个数组对象了。但是这只是编译器的语法糖,且支持传入的基本类型而方法声明的是包装类的自动装箱。如果你传入的本来是一个数组,则编译器就不会帮你组成数组了。
      24.创建枚举:
      public enum Season{SPRING,SUMMER=100,AUTUMN,WINTER}
      编译器会自动添加每一个具名的toString方法。还有ordinal方法,表示某个具名的声明顺序(从0开始,也可以自己制定一个开始),还有一个static values方法,产生按照声明顺序组成的枚举引用数组。
      使用枚举: Season s = Season.SPRING;
      枚举用在switch中很方便,case可以直接使用具名。
  • 相关阅读:
    Microsoft NLayerApp“.NET研究”案例理论与实践 项目简介与环境搭建 狼人:
    .NET中的“.NET研究”异步编程:使用F#简化异步编程 狼人:
    ASP.NET MV“.NET研究”C3 基础教程 – Web Pages 1.0 狼人:
    引用“.NET研究”类型赋值为null与加速垃圾回收 狼人:
    使用WCF实现SOA面向服务编程“.NET研究”—— 架构设计 狼人:
    MEF——.NET中值“.NET研究”得体验的精妙设计 狼人:
    Silverlight“.NET研究” 2.5D RPG游戏技巧与特效处理:(十)空间分层战斗系统 狼人:
    再次分享一个多选文件上传方案“.NET研究” 狼人:
    C#中标准Dis“.NET研究”pose模式的实现 狼人:
    .NET中的异步编程 IO完成端口以及FileStream.“.NET研究”BeginRead 狼人:
  • 原文地址:https://www.cnblogs.com/yumingle/p/6659886.html
Copyright © 2020-2023  润新知