日志分类:基础

对象实例化的顺序

分类:java, 基础评论:6条作者:ticmy日期:2012-11-08

创建一个对象大概有以下几种方式: 1、通过new关键字,如new Object(); 2、通过某些反射类的newInstance方法,如Class#newInstance、Constructor#newInstance; 3、如果对象是Cloneable的,通过clone方法; 4、通过ObjectInputStream#readObject反序列化; 以上是通过java程序可以创建出对象的方式,jvm中还有一些隐式创建对象的地方,譬如: 1、启动一个类,main方法的参数String数组是隐式创建的,如果指定了一个或多个String对象,还要创建这些String对象; 2、读入一个class二进制数据的时候,创建一个与之对应的java.lang.Class类的对象; 3、在使用“+”进行字符串变量连接时,可能会创建StringBuffer/StringBuilder对象; 如此等等。 那么,在程序中通过new或newInstance创建对象(后面说创建对象均指这两种方式)的时候,构造方法、实例变量、父类构造方法、父类实例变量等的执行顺序是怎样的? 在创建对象的时候,首先会分配内存,此时所有实例变量均为默认值,然后做初始化实例变量、构造方法调用等操作。对于类变量,在创建对象之前,加载类的时候已经做掉了,这里为避免干扰,忽略掉。 先来一个例子: public class Init { public static v…

+=与=..+..的区别

分类:java, 基础评论:11条作者:ticmy日期:2012-09-28

在书本中,课堂上,关于a+=b大都说等价于a = a+b,其实不然,+=中包含着更多的东西。 在继续之前,来温故一点基础(为简单起见,只说整数)。 1、做基本运算(如+、-、*、/、、>>>、~、^等),当两个操作数的类型是byte,short,char,int之一的时候,结果的类型是int; 2、做整数基本运算时,当一个操作数是long,结果是long; 3、不加任何修饰的整数字面值默认就是int类型。 下面对上面的几点举例说明: short s1 = 1;//OK short s2 = s1 + 1;//ERROR 上面的第一句1整形字面值,它的类型是int,为什么可以直接赋值给short呢?因为字面值都是常量,编译器能很容易的检测出它到底在不在short所能表示的值的范围内。当写成short s1 = 32768的时候,编译就知道short容不下32768了,就会报错。 而对于第二句,s1是short类型,1是int类型,结果是int类型,自然不能自动赋值给short类型的s2了,因为有潜在的高位有效值被截断的风险。可能会有人想,上面s1已经赋值了一个字面值,对于下面的s2,编译器应该也可以计算出它的值啊。如果s1是final的,确实会这样,但s1是变量,编译器是无法预测它会不会在运行期改变的,即使它可能不会改变。 再来一个,计算一年有多少毫秒…

JDBC在getConnection之前为什么要调用Class.forName

分类:java, 基础评论:15条作者:ticmy日期:2012-08-24

获取一个数据库连接的通用模板如下: String driver = "oracle.jdbc.OracleDriver"; String url = "jdbc:oracle:thin:@127.0.0.1:1521:orcl"; String user = "scott"; String password = "ticmy"; Class.forName(driver); Connection conn = DriverManager.getConnection(url, user, password); 里面有个Class.forName(driver),这句话有什么作用?将驱动类load到内存?如果没有这句会怎么样?运行发现,如果去掉这一句会有以下异常: java.sql.SQLException: No suitable driver found for xxx…. 在解释具体原因之前先简单看下Class.forName做了什么。 假设一个类以前从来没有被装进内存过,Class.forName(String className)这个方法会做以下几件事情: 1、装载。将字节码读入内存,并产生一个与之对应的java.lang.Class类对象 2、连接。这一步会验证字节码,为static变量分配内存,并赋默认值(0或null),并可选的解析符号引用(这里不理解没关系) 3、初始化。为类的static变量赋初始值,假如有static int a = 1;这个将a赋值为1的操作就是这个时候做的。除此之外,还要调用类的static…
Tags:

Wait-Notify机制

分类:java, 基础, 并发评论:6条作者:ticmy日期:2012-07-21

Wait-Notify机制可以说是实现阻塞操作较为高效的一种方式。虽然在实际中鼓励使用类库中已有的满足条件的类,或基于类库中的类来做满足自己特殊需求的开发,并不建议直接使用如此底层的机制,但了解其原理还是很有必要的。 典型的Wait-Notify场景一般与以下内容相关: 1、状态变量(State Variable) 当线程需要wait的时候,总是因为一些状态不满足导致的。如往BlockingQueue里加元素队列已满的时候。当状态满足的时候,程序就可以执行下去。 2、条件断言(Condition Predicate) 当线程确定是否进入wait或者从notify中醒来的时候是否继续往下执行,大都要测试状态条件是否满足,如往BlockingQueue里加元素队列已满,于是阻塞,后续其它线程从队列里取走了元素,就通知在等待的线程“队列不是满的了,可以往里加东西了”,这时候在等待的线程就会醒来,然后看看是不是真的队列不为满的状态,如果是,就将元素添加进去,如果不是,就继续等待。 3、条件队列(Condition Queue) 每个对象都有一个内置的条件队列,当一个线程在该对象是调用wait的时候,就会将该线程加入该对象的条件队列。 基于以上,接下来说说wait(以及其它两个带超时时间的wait重载版本,后文…

Java反射详解

分类:java, 基础评论:12条作者:ticmy日期:2012-07-20

反射,是Java中非常重要的一个功能,如果没有反射,可以说很多框架都难以实现。 什么是反射?说白了就是可以通过Java代码获取装载到方法区的类信息的手段。 当装载一个类时,会在方法区产生一个数据结构,该结构中包含着装载的类的相关信息。字节码可以看成是数据流,那么方法区的这种数据结构可以说是字节码数据流的结构化表现。装载的最终产物就是java.lang.Class类的一个对象,它是Java程序与方法区内部数据结构之间的接口。 那么,我们能通过这个接口访问内部数据结构的哪些信息呢?接下来介绍关于反射常用的一些内容。反射的大部分方法大都与安全管理器有关,本文忽略此部分。 假设有以下代码(一个简单的文章管理代码) package com.ticmy.reflect; /** * 文章管理接口 * @author Administrator */ public interface ArticleInterface { public void del(long id) throws Exception; public void add(String content) throws Exception; public void modify(long id, String content) throws Exception; } 一个简单实现 package com.ticmy.reflect; import java.util.Map; import java.util.Random; import java.util.concur…
Tags: ,

equals和==

分类:java, 基础评论:5条作者:ticmy日期:2012-07-10

很多不明真相的javaer喜欢纠结于此问题,特来解释一二。 先看代码 StringBuilder s1 = new StringBuilder(); StringBuilder s2 = new StringBuilder(); String s = "abc"; s1.append(s); s2.append(s); System.out.println("s1.equals(s2):\t\t" + (s1.equals(s2))); System.out.println("s1 == s2:\t\t" + (s1 == s2)); String s3 = s + "1"; String s4 = s + "1"; System.out.println("s3 == s4:\t\t" + (s3 == s4)); System.out.println("s3.equals(s4):\t\t" + (s3.equals(s4))); Object obj1 = new Object(); Object obj2 = new Object(); System.out.println("obj1.equals(obj2):\t" + (obj1.equals(obj2))); System.out.println("obj1 == obj2:\t\t" + (obj1 == obj2)); 执行结果如下 s1.equals(s2): false s1 == s2: false s3 == s4: false s3.equals(s4): true obj1.equals(obj2): false obj1 == obj2: false 有人说“==比较地址,equals比较内容”,从String的比较来看这是对的,但从上述StringBuilder来…