idea里查看uml类图

生成方法

Show Diagrams

  • 选中需要的类,右键单击Diagrams,之后点击Show Diagrams,或者快捷键Ctrl+Alt+Shift+U
  • 生成类图,将类图显示在编辑器窗口中

Show Diagrams PopUp

  • 选中所需要类,右键单击Diagrams,之后点击Show Diagrams PopUp,或者快捷键Ctrl+Alt+U
  • 生成类图,将类图显示在弹出窗口中

泛化(Generalization)

  • 代码(体现在类的继承)
  • 类图(实线三角形箭头,指向父类)

实现(Realization)

  • 代码(体现在类的实现)
  • 类图(虚线三角形箭头,指向父类)

依赖(Dependency)

代码(体现在局部变量、方法的参数或者对静态方法的调用)

  • 类图(虚线普通箭头,指向被调用者,其中带有create的虚线是指创建(new)被调用者)

关联(Association)、聚合(Aggregation)、组合(Composition)

  • 区别
    三者在代码上的表现相同,只是语意上有所差别。
    组合:整体和部分同生共死,部分无法离开整体单独存在
    聚合:部分可以离开整体单独存在
    关联:代表一种拥有关系
  • 代码(体现在成员变量中)
  • 类图(三种类型在IntelliJ IDEA均以实线+菱形箭头+普通箭头表示,菱形箭头指向整体,普通箭头指向部分,箭头两端的数字表示实例的个数)
0

idea里使用jclasslib Bytecode viewer插件代替javap命令查看字节码

前言

我们在写或读java代码时,有些时候(如语法糖等)很难理解JVM的具体执行细节,当然可以通过javap反编译来查看JVM字节码。但是每次都要敲命令,不免有些繁琐。在ide中,可以通过jclasslib Bytecode viewer插件工具来更细节地观察某类的字节码信息。

安装

在idea的插件安装界面,搜索jclasslib Bytecode viewer,然后点击install,然后点击restart。

使用

重启ide后,点击某个类,在工具栏view中可以看到show bytecode的选项,如下:

新建一个Test类

编译好后,点击show bytecode,可以看到完整的字节码信息

当然,也可以点击 Show ByteCode with Jclasslib,这时可以看到该类的基本信息、常量池、接口、属性、函数等信息。

另外,如果想了解某个具体字节码指令的含义,可以点击它,就会跳转到 java虚拟机规范对应的章节。

假设咱们想看iconst_1,点击它

更细节的功能,大家自行挖掘吧。

0

面试题:Jvm的Hotspot的锁升级?

这边主要有三种锁的名词:偏向锁自旋锁重量级锁

之前《Java锁synchronized关键字原理的Mark Word理解》这篇文章有讲到synchronized的一些实现原理,就是在存储的Java对象的头信息里记录线程的一些信息,其中就有记录是否是偏向锁。

当线程A第一次拿到锁后,会在头信息里记录下线程A的id,然后当下次如果还是线程A拿到锁进来,那jvm就直接根据是否是偏向锁来决定是否允许它进来,也就是说这个时候其实并没有涉及到真正的锁,只是一个简单的判断。

当线程B准备竞争锁时,它会先进入到一个轻量级的锁——自旋锁,这时就相当于一个while循环(默认是10次),这时主要消耗的是cpu资源。

当自旋超过10次后,这时就会像线程C那样,开始升级申请操作系统的重量级锁,然后进入等待队列。

从中可以看出,当业务里有大量耗时长的线程时,是不适宜使用自旋锁的,因为那将非常消耗cpu资源。

0

面试题:Java线程里抛出异常会释放锁吗?

为了验证这个问题,写了一段代码来验证,它可以保证线程1先执行,如果线程1不抛出异常,那它应该一直循环输出,线程2根本进不来。

那如果抛出了异常,可以看看执行结果。

输出

+1

Java锁synchronized关键字原理的Mark Word理解

synchronized是Java里锁使用的关键字,而synchronized的底层jvm实现是依赖一个交monitor的对象。monitor管理锁的持有者的进入和退出。

当synchronized用来修饰同步代码块时,这时是由monitorenter和monitorexit指令来控制同步的。

有下面这段代码

利用jdk自带的javap命令进行解析字节码文件

其中主要关注如下信息

其中monitorenter指令指向同步代码块的开始位置,monitorexit指令则指明同步代码块的结束位置。

当执行monitorenter指令时,当前线程将试图获取 objectref(即对象锁) 所对应的 monitor 的持有权,当 objectref 的 monitor 的进入计数器为 0,那线程可以成功取得 monitor,并将计数器值设置为 1,取锁成功。

如果当前线程已经拥有 objectref 的 monitor 的持有权,那它可以重入这个 monitor (关于重入性稍后会分析),重入时计数器的值也会加 1。

倘若其他线程已经拥有 objectref 的 monitor 的所有权,那当前线程将被阻塞,直到正在执行线程执行完毕,即monitorexit指令被执行,执行线程将释放 monitor(锁)并设置计数器值为0 ,其他线程将有机会持有 monitor 。

值得注意的是编译器将会确保无论方法通过何种方式完成,方法中调用过的每条 monitorenter 指令都有执行其对应 monitorexit 指令,而无论这个方法是正常结束还是异常结束。为了保证在方法异常完成时 monitorenter 和 monitorexit 指令依然可以正确配对执行,编译器会自动产生一个异常处理器,这个异常处理器声明可处理所有的异常,它的目的就是用来执行 monitorexit 指令。

从字节码中也可以看出多了一个monitorexit指令,它就是异常结束时被执行的释放monitor 的指令。

0

Java里使用Arrays.sort对数组进行排序

Java 语言使用 java.util.Arrays 类提供的 sort() 方法来对数组进行排序。

升序

降序

方法1
方法2
0

java里使用Thumbnails进行指定大小压缩图片

以下是java压缩图片至指定大小的代码

代码里的imageId仅做日志输出用途,getAccuracy()方法是本人测试了几张图片后得出的经验数值(为了减少循环次数),也可以不用,直接传入压缩质量比即可。

0

Java将List转换为逗号分隔的字符串

1.利用Guava的Joiner

List list = new ArrayList();
list.add(“a”);
list.add(“b”);
list.add(“c”);

String str = Joiner.on(“,”).join(list);

2.利用Apache Commons的StringUtils

List list = new ArrayList();
list.add(“a”);
list.add(“b”);
list.add(“c”);

String str = StringUtils.join(list.toArray(), “,”);

0

语法糖是什么?

什么是语法糖

简单的说,语法糖就是一种便捷的写法。

语法糖就相当于汉语里的成语。即,用更简练的言语表达较复杂的含义。在得到广泛接受的情况之下,可以提升交流的效率。

例如:

它其实就是:

可以简单理解为,加糖后的代码编译后跟加糖前完全一样。

由示例可以看出,语法糖的使用其实就是让我们的写的代码更简单,看起来也更容易理解。

0