开发一路走开算算也有4个年头,学习两年工作两年。一直所使用都是Java,在工作中除了学到一些解决问题的办法之外对于Java来说无任何收获。现在依然还是一个搞不清东南西北的低贱程序员,只管写代码不注意细节,所以也酿成了不少的Bug、漏洞。决定写一篇日志记录下以前开发之中的一些未解决的疑惑。当然你也可以对解答的内容进行评论,或者帮忙解答(解答就请给出说明和示例)
1.static修饰的变量、方法、类的一些基础,是否属于多线程安全2.final修饰符的一些作用,适用于什么场合3.接口、抽象类的适用场合、类的继承关系适用场合4.资源开销5.array、list、map、set之间的数据转换6.多线程的一些操作7.文件操作及nio包8.一些排序方式和基础算法9.一些常用的模式10.StringBuffer和StringBuilder的一些区别从Java API文档中可以知道,StringBuilder提供基于StringBuffer兼容的API,唯独不同的地方是StringBuilder不是基于线程同步的,所以执行的效率也要高于StringBuffer,建议优先使用该类。他们都提供了append和insert方法,append方法是在原有的基础上追加一个string对象,insert方法提供了按位追加第一个参数可以设置追加的位置,例: 缓冲区中默认已有start字符串,sb.insert(4, "abc") 返回的缓冲区对象为“starabc”。当所有追加的字符串过多的时候,可以在创建对象的时候设置缓冲区的大小以减少缓冲区扩充容量时候的资源消耗。11.异常处理的不同操作方式我目前所知道的异常处理可以分为三种不同的场景和两种模式的异常(运行时异常、非运行时异常)一、异常代码处无法对异常内容进行相关操作需要,也就是catch内无法对异常进行相关的处理。例如下图:此段代码是根据传入的url转换成url对象然后连接此对象并读取其内容,中间需要对两种非运行时异常进行捕获。但是在catch范围内无法处理此异常内容,那么我们就需要把异常往上抛出,由上面的类捕获进行处理,比如需要给用户解释为什么获取不到信息,究竟是url错误了还是读取内容的时候出错了呢?我们需要把这些错误内容展示给用户。但为什么又需要try这段代码呢,因为当出现异常的时候我们需要对连接对象进行销毁操作。二、异常无法操作,但又不需要对代码本身做什么的时候我们就不会try这些代码,直接把异常往上抛出即可。例如下图:我们在解析xml内容的时候,需要主动处理一个一场对象,但是我们在此处无法处理该异常信息,那么我们就需要向上抛出这个异常。三、此处代码可以进行异常操作的时候我们就不需要网上抛出异常。例如:仅关闭连接对象不用反馈用户,或者是读写文件的时候出现异常了,我们需要未写完的文件。以上的三种方法仅说明于非运行时异常,当然运行时异常也可以这么处理。12.枚举类型(Enum)在jdk1.5中提供了枚举类型,你可以把他当做一个限制级的类来看,可以这么理解,枚举类中所有的定义都被加于final修饰,类、构造方法、枚举值。枚举类中主要用于定义一些枚举类型(即常量),因此在定义枚举字段时最好大写。枚举类中是存在构造方法的,但是它不能创建实例对象,所以构造器不能使用public修饰。构造方法的主要作用是指引枚举值的定义范义,如果你不能够理解这句话的话,可以下面的代码。上面的代码中需要定义枚举值的值内容,如果使用此种方法定义,必须依赖于构造器的参数。如果定义的枚举值的值是本身的话也可以使用下面的写法。此种写法枚举值的值是本身,即Color.RED的值为:“RED”PS:枚举很适合创建一系列具有相同类型值的集合,而且枚举值本身也支持switch遍历。13.对象锁(synchronized)同步加锁的是对象实例,而不是代码。因此,如果你的类中有一个同步方法,这个方法可以被两个不同的线程同时执行,只要每个线程自己创建一个的该类的实例即可。1).如果一个对象有多个synchronized方法,只要一个线程访问了其中的一个synchronized方法,其它线程不能同时访问这个对象中任何一个synchronized方法。2).除了方法前用synchronized关键字,synchronized关键字还可以用于方法中的某个区块中,表示只对这个区块的资源实行互斥访问。用法是: synchronized(this){/*区块*/},它的作用域是当前对象;一、当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。二、然而,当一个线程访问object的一个synchronized(this)同步代码块时,另一个线程仍然可以访问该object中的非synchronized(this)同步代码块。三、尤其关键的是,当一个线程访问object的一个synchronized(this)同步代码块时,其他线程对object中所有其它synchronized(this)同步代码块的访问将被阻塞。四、第三个例子同样适用其它同步代码块。也就是说,当一个线程访问object的一个synchronized(this)同步代码块时,它就获得了这个object的对象锁。结果,其它线程对该object对象所有同步代码部分的访问都被暂时阻塞。五、以上规则对其它对象锁同样适用.引用地址:14.单例模式引用地址:15.线程Thread、Runnable、CallableJDK 1.5提供了三种线程的实现方式,Thread、Runnable、Callable,下面就介绍下三种的具体作用和实现方式。Thread和Runnable 我们都已经很熟悉了,是JDK中最早实现的两种基于线程的实现方式,Thread提供了继承的实现模式,任何类继承至该类即可以实现线程,然后重写父类继承的run方法,并通过start方法调用启动一个线程,当然直接调用run方法无效,相当去执行了run中的代码,并未开启一个新的线程。Runnable 是以接口的模式提供多线程的实现方式,在Java中一个类最多只能继承一个类,使用Runnable接口来实现多线程弥补了Thread的不足之处,使用方法都是相同的,只是在创建线程对象的时候需要把对象放置于Thread对象之中,通过Thread去管理线程对象。Callable可能大多数人都没怎么了解过,我也是今天才在ITEYE上了解,然后看了下API,Callabel和Runnable相同,不同之处是可以返回执行的结果和定义异常。线程运行之后,可以通过调用get方法获取到返回的值,也可以使用cancel中断当前线程的执行。此类需要使用FutureTask包装,然后丢给Thread去执行。Future是继承与Runnable接口,同时也可以包装Runnable接口的对象。16.各种情况下geResource()、getResourceAsStream()的一些介绍getResource是返回指定文件的URL形式的对象,getResourceAsStream是返回指定文件的InputStream对象,下面介绍了几种常用获取项目文件路径的方法,可以实现项目中文件路径的软编码形式。下面介绍一下三种:Class.getResource(filename) 返回当前类路径的相对路径,如果参数filename属于当前类路径下的文件,那么可以返回该文件的URL形式对象。如果filename为空字符串,则返回当前类的绝对路径。其实是用该方法可以省略绝对路径,参数可以是用该类的路径定位相对路径。ClassLoader.getResource() 和上面的形式差不多,只是相对路径为当前工程的classpath,也就是编译文件的顶路径。Thread.currentThread().getContextClassLoader().getResource() 和上面的一样,不同的地方在于,是返回当前线程的classpath,因为每个线程可以设置属于自己的setContextClassLoader,为了在多线程下区分出对应线程的ContextClassLoader故使用该方法返回。建议最好使用最后一种方式获取文件的路径或者项目的classpath,比较安全。相关参考: