Skip to content
Ider

沉淀我所学习,累积我所见闻,分享我所体验

Primary Navigation Menu
Menu
  • Home
  • About Ider
    • Who Ider?
    • Why Ider?
    • How Ider?
    • Where Ider?
    • What Ider?

Initialization

2018-06-29
29 June
On June 29, 2018
In Data Structures(数据结构), Design Patterns(设计模式), Language Tips(语言初试)

隐秘而诡异的Java合成方法

Java程序里其实有很多我们看不到的代码,这些代码由Java编译器在编译过程中生成帮助程序更准确地运行。本文就来深入了解一下由编译器加入到Java代码中的方法(Method),特别是合成方法(Synthetic Method)。

合成方法

合成成员(Synthetic Member)在JVM细则里可以找到简单的定义

A class member that does not appear in the source code must be marked using a Synthetic attribute, or else it must have its ACC_SYNTHETIC flag set.

合成成员包含有合成类(Synthetic Class),合成变量(Synthetic Variable),合成方法(Synthetic Method),本文主要讨论合成方法。

合成方法不出现在.java文件中,不过编译之后会在.class里出现,并可以通过以下几个方法发现它们:

  • 在设置断点进行debug时会在方法栈上看到这些由编译器加入的方法
  • 通过反射(Reflection)查找到方法,通过isSyntehtic()方法来判定是否是合成函数
  • 利用一些反编译工具,比如 javap、JD-GUI、jad,查看.class文件可以找到这些方法

对于一般的Java程序而言并没有什么大的问题,只不过是额外的方法调用,代价比较低。但是像Android,它的Dex文件对于Java的方法有一定的约束,就值得去考虑如何避免额外的方法被生成。下边就来介绍一些常见的会出现合成方法的情况让我们有清楚地了解Java的运行机制。

嵌套类和私有成员

先来看一个代码案例,代码中定义了一个顶层类和嵌套类,互相会方法对方的一些private修饰的方法和字段。

[codesyntax lang=”java” lines=”normal”]

public class Outer {

  private int privateField = 21;
  private Inner inner = new Inner();

  private int privateMethod() {
    return inner.privateMethod();
  }

  private void print() {
    inner.print();
  }

  private static int privateStaticMethod() {
    return 7;
  }

  class Inner {
    private int privateMethod() {
      return privateField;
    }

    private void print() {
      System.out.println(Outer.this.privateMethod());
      System.out.println(privateStaticMethod());
    }
  }

  public static void main(String[] args) {
    Outer outer = new Outer();
    outer.print();
  }
}

[/codesyntax]

之前的文章有介绍了Java的修饰访问符的限制范围,类中由private修饰的成员,只能被该类自身所访问,因此嵌套类的私有成员不应该能被外部类访问。另一方面嵌套类虽然在外部类里面,但其实并不属于外部类的一部分,比如编译上边的代码会得到两个.class文件,Inner类被编译成了package可见的独立类。


Read More →

2013-02-21
21 February
On February 21, 2013
In Design Patterns(设计模式), Knowledge Base(心得笔库), Language Tips(语言初试)

DOM的JavaScript事件绑定方式比较

JavaScript语言是当前十分流行的语言。它从前端页面走来,产生了像jQuery这样的强大框架;它向后端服务器走去,有了Node.js;它更被微软接受为平等于C#和VB.net的第三种可用于开发Windows8应用的语言。

不过说到底,JavaScript的本家还是在前段网页界面的上的使用,而真正让JavaScript变得如此强大的还在于它能对文档对象模型(Document Object Model),也就是俗称的DOM进行操作。这其中,又要数“事件处理(Event Handling)”让用户交互(User Interaction)体验得到了巨大的提升和丰富。

如果没有事件处理,其实根本不会需要添加JavaScript到页面上,本篇文章就来总结一下JavaScript中DOM事件绑定和激发的一些方式和机制,有助于在以后的开发上有更好的设计和理解。
Read More →

2012-10-26
26 October
On October 26, 2012
In Design Patterns(设计模式), Language Tips(语言初试)

Objective-C简单对象关系映射(ORM)结构

用+(void)load对全局变量初始化,实际上并不是一个非常好应用,因为大多情况下我们并不需要使用全局变量。但是另一方面,我们倒是可以通过+(void)load来实现对象关系映射(Object-relational mapping, ORM)的结构。

首先我们要定义一个ORM类,它含有Dictionary成员。这个Dictionary用来保存我们要用来映射对象所属类的名字(作为key)和类本身(作为value)。
Read More →

2012-10-26
26 October
On October 26, 2012
In Knowledge Base(心得笔库), Language Tips(语言初试)

使用Objective-C的+(void)load初始化全局变量

《Objective C类方法load和initialize的区别》里,我介绍了+(void)initialize和+(void)load两个方法在编译和执行时出现的区别,又通过《使用Objective-C的+(void)initialize初始化static变量》一文简单介绍了+(void)initialize可以用在对静态变量的初始化上。

如同《使用Objective-C的+(void)initialize初始化static变量》中介绍的那样,假如Objective-C的全局变量被限定为static,只用在当前文档中,那么使用+(void)initialize来进行初始化是非常合适而且正确的。如果类并未被使用,该变量就不会被赋予对象也就不会浪费内存空间。但是假如我们就是希望用全局变量在程序任何地方使用,那么+(void)initialize可能就不那么有效了。因为变量可能在相应类的方法被调用前就使用,即是说+(void)initialize并未被调用对全局变量进行初始化。
Read More →

2012-10-23
23 October
On October 23, 2012
In Knowledge Base(心得笔库), Language Tips(语言初试)

使用Objective-C的+(void)initialize初始化static变量

在《Objective C类方法load和initialize的区别》一文中,我介绍了Objective-C对待+(void)initialize和+(void)load两个方法在编译和执行时出现的不同。而这些不同也是在使用时应该非常注意的地方。不过文章里面我没有讲这两个方法在Objective-C中究竟有什么实用价值。

其实+(void)initialize可以视为C#,Java中的静态构造函数。有了这个方法,我们就不用像C++自己另找途径来设计静态构造函数了。不过Objective-C中又有一些很不同的地方,因为Objective-C里不能把数据成员限定为static或者const。也就是说,虽然Objective-C可以定义类方法,但是类不能有数据成员。所以也不存在静态数据成员初始化的问题。

不过作为C语言的超集,Objective-C依然可以沿用C的一些特点了定义static的全局变量来作为类静态成员。
Read More →

2012-09-29
29 September
On September 29, 2012
In Knowledge Base(心得笔库), Language Tips(语言初试)

Objective C类方法load和initialize的区别

过去两个星期里,为了完成一个工作,接触到了NSObject中非常特别的两个类方法(Class Method)。它们的特别之处,在于iOS会在运行期提前并且自动调用这两个方法,而且很多对于类方法的规则(比如继承,类别(Category))都有不同的处理。

而因为这两个方法是在程序运行一开始就被调用的方法,我们可以利用他们在类被使用前,做一些预处理工作。比如我碰到的就是让类自动将自身类名保存到一个NSDictionary中。

Read More →

2012-04-10
10 April
On April 10, 2012
In Data Structures(数据结构), Language Tips(语言初试)

C++仿制静态构造函数

在《C++的头文件和实现文件分别写什么》文章中,我对于的C++的数据成员,逐个分析了可以作用在它们上边的限定符都有哪些,以及它们所对应的进行初始化的位置。可以看出这些修饰符其实就是const和static的两种的组合,但是却有不同的效用。

本文,我想讲关于static的问题,《C++的头文件和实现文件分别写什么》已经指出如果数据成员被声明为static,那么它在编译时就必须被初始化。仅含static的则放在类之外,实现文件之中;同时含有的const的则放在类之内,直接跟在数据的定义之后。

在我实际代码编写中碰到的问题是:static成员的初始化比较的复杂,步骤较多,需要调用另一个函数来完成。此时,简单使用赋值语句就不太能完成那些目的了。
Read More →

Facebook
Twitter
LinkedIn
RSS
ZhiHu

Recent Posts

  • 三年居家工作感受
  • Pixel Watch智能手表和Pixel 5, 6 Pro 及 7 Pro手机
  • 我拥有过的无线耳机
  • 毕业工作一个月,我差点被开除
  • 我拥有过的移动硬盘
  • ProtoBuf 2.0 method count optimization for android development
  • 面过100场行为面试后

Categories

  • Algorithm Analysis(算法分析)
  • Article Collection(聚宝收藏)
  • Data Structures(数据结构)
  • Design Patterns(设计模式)
  • English Posts(英文写作)
  • Front Interface(界面构想)
  • IT Products(数码产品)
  • Knowledge Base(心得笔库)
  • Language Tips(语言初试)
  • Mathematical Theory(数学理论)
  • Mobile Development(移动开发)
  • Programming Life(程序人生)
  • Reading Notes(阅而后知)
  • Software Engineering(软件工程)
  • Special Tricks(奇技妙招)
  • Tangential Speech(漫话杂谈)

Tags

Aero Android API Bash Binary Search Bitwise Operation Book C/C++ Career Chrome Conference CSS Debug Device DOM Extension Framework Game Gradle Hearthstone HTML Initialization Intellij Interview iOS Java JavaScript jQuery Keyword Language Issues Mac Microsoft Mobile Modifier Objective-C PHP Principle Reference Regular Expression Static String Tools Tutorial UI XML

Blogroll

  • Ahmed's Blog
  • Gert Lombard's Blog
  • Gordon Luk
  • Jack & Allison
  • 开发部落

Archives

Designed using Chromatic. Powered by WordPress.