Java中final关键字总结

final在java中的用法有很多,可以修饰field,可以修饰Method,可以修饰Class,而且final在多线程环境中保证了对象状态的不变性,下面就系统的总结一下Java中final关键字的用法 修饰Variable/field 修饰primitive变量,变量一旦赋值就不再可变。 final修饰基本数据类型变量和String类型时,类似于C++的const 3种变量会被隐式的定义为final:3.1. 接口中的field是final的3.2. Java7中出现的try with resource语句中的变量是隐式的final类型,如下面的代码,inputStream虽然未被声明为final,但是如果试图在try块里面重新对inputStream赋值的话,就会产生编译异常,不能给final变量赋值 12345try (FileInputStream inputStream = new FileInputStream("text.txt")){inputStream = new FileInputStream("");} catch (Exception e) { e.printStackTrace();} 修饰引用实例类型变量,变量被赋值后,变量指向的引用的值可以变,但是不能重新指向新的引用,即final只关心引用本身,而不关心final引用的内容。 12345678public static void main(String[] args) { final User user = new User("xuan1",23); System.out.println(user.getAge()); //输出23 user.setAge(24); System.out.println(user.getAge()); //输出24 user = new User("xuan2",25); //编译错误,提示不能赋值给final变量 System.out.println(user.getAge());} 修饰实例成员变量时,必须在定义的时候初始化:直接赋值,构造器初始化,或代码块中初始化,或的意思是这三种方式只能选择一种,否则编译报错。 修饰静态成员变量时,必须在变量定义的时候初始化:直接赋值,静态代码块中赋值 Tips: 有一种特殊情况:System.in,System.out,System.err 是静态域但是没有在定义的时候或者静态代码块中初始化,而是使用了set方法来设置值。 JDK8以前内部类访问外部类的变量时要求变量为Final类型,JDK8之后,只要求外部类为事实不可变变量,不一定要加上final

java

intellij idea中使用javap等JDK工具

java工程师平时工作中用到的工具挺多的,比如javap,jstack等,intellij idea 作为宇宙最强java ide idea一样可以帮我们实现这个功能,方法如下: ctrl+alt+s打开设置界面,找到Tool-> External Tools 点击 +来增加一个新的外部工具。

java

Java中将JSON反序列化为泛型对象

将嵌套List的Map转换为Json应该都没什么问题,使用Gson和Jackson都能实现,在Gson中使用new Gson().toJson()方法,在Jackson中使用new ObjectMapper().writeValueAsString()即可。将json转换为形如Map<String,List>的时候遇到了一点问题,虽然返回类型是Map<String,List<Long>>但是,Map的value的值却并不是List<Long>,而是Integer类型的,这里面显然是有问题的,查看Jackson的源码和Gson的源码发现将json反序列化为对象确实有两个方法,一种适用于泛型对象,一种适用于非泛型的一般对象。 使用Gson在gson中将json字符串转反序列化为对象有两个方法: 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950 /** * This method deserializes the specified Json into an object of the specified class. It is not * suitable to use if the specified class is a generic type since it will not have the generic * type information because of the Type Erasure feature of Java. Therefore, this method should not * be used if the desired type is a generic type. Note that this method works fine if the any of * the fields of the specified object are generics, just the object itself should not be a * generic type. For the cases when the object is of generic type, invoke * {@link #fromJson(String, Type)}. If you have the Json in a {@link Reader} instead of * a String, use {@link #fromJson(Reader, Class)} instead. * * @param <T> the type of the desired object * @param json the string from which the object is to be deserialized * @param classOfT the class of T * @return an object of type T from the string. Returns {@code null} if {@code json} is {@code null}. * @throws JsonSyntaxException if json is not a valid representation for an object of type * classOfT */public <T> T fromJson(String json, Class<T> classOfT) throws JsonSyntaxException { Object object = fromJson(json, (Type) classOfT); return Primitives.wrap(classOfT).cast(object); } /** * This method deserializes the specified Json into an object of the specified type. This method * is useful if the specified object is a generic type. For non-generic objects, use * {@link #fromJson(String, Class)} instead. If you have the Json in a {@link Reader} instead of * a String, use {@link #fromJson(Reader, Type)} instead. * * @param <T> the type of the desired object * @param json the string from which the object is to be deserialized * @param typeOfT The specific genericized type of src. You can obtain this type by using the * {@link com.google.gson.reflect.TypeToken} class. For example, to get the type for * {@code Collection<Foo>}, you should use: * <pre> * Type typeOfT = new TypeToken&lt;Collection&lt;Foo&gt;&gt;(){}.getType(); * </pre> * @return an object of type T from the string. Returns {@code null} if {@code json} is {@code null}. * @throws JsonParseException if json is not a valid representation for an object of type typeOfT * @throws JsonSyntaxException if json is not a valid representation for an object of type */ @SuppressWarnings("unchecked") public <T> T fromJson(String json, Type typeOfT) throws JsonSyntaxException { if (json == null) { return null; } StringReader reader = new StringReader(json); T target = (T) fromJson(reader, typeOfT); return target; }

java

Java中的互斥锁和读写锁

在JDK5之前,访问共享对象的时候使用的机制只有synchronized和volatile ,JDK5的并发包里提供了一种新的更加高级的机制:互斥锁ReentrantLock,显式锁是为了弥补内置锁的方法而开发的,两者是互补的关系,显式锁并不能代替内置锁。ReentrantLock实现了一种标准的互斥锁,亦即每次最多有一个线程能够持有ReentrantLock Lock接口&ReentrantLock简介concurrent包中的Lock类定义了一组抽象的加锁操作,如下代码所示,与synchronized不同的是,Lock提供了一种无条件、可轮询、定时、可中断的锁获取操作,所有的加锁和解锁操作都是显示的ReentrantLock实现了Lock接口,提供了与synchronized相同的互斥性以及内存可见性。与synchronized一样,ReentrantLock提供了可重入(即可以被单个线程多次获取)的加锁语义。 123456789public interface Lock { void lock(); void lockInterruptibly() throws InterruptedException; boolean tryLock(); boolean tryLock(long time, TimeUnit unit) throws InterruptedException; void unlock(); Condition newCondition();} ReentrantLock的使用方法: 12345678Lock lock = new ReentrantLock();...lock.lock();try{} finally{ lock.unlock();} 在使用显示锁的时候一定要在finally块中释放锁,否则如果代码中一旦出现异常,那么可能这个锁永远都无法释放就会造成某个对象的状态不一致,如果是账户余额或者别的重要的信息可能就会出现很严重的事故。

java

使用Btrace来跟踪调试代码

有的时候在写程序的时候可能有些地方的日志没有照顾到,产生了bug,如果到了线上环境,有时候不得不停掉服务重新来加入日志来查看产生bug的地方,这个时候Btrace就派的上用场了,在VisualVM中可以很方便的调试目标程序,而对原有项目没有影响,当然也可以不用VisualVM而使用命令行来实现这个功能。Btrace是一个开源项目,项目托管在github上 使用VisualVM的Btrace插件最为方便,下面就写个小例子来熟悉一下 准备工作1.在visualvm官网下载visualVM可视化工具2.依次点击visualVM菜单栏的Tool->plugins打开插件窗口,选择 Btrace workBench 然后一路 next安装 目标程序 准备了一个简单的小程序:从键盘接收两个数字然后计算两个数字之和,主要目的是方便下一步用Btrace来调试打印出方法的参数的值,以及堆栈信息 12345678910111213141516171819202122232425package org.xuan.trace;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;/** * Created by Xuan on 2016/9/10. */public class BTraceTest { public int add(int a ,int b){ return a+b; } public static void main(String[] args) throws IOException { BTraceTest traceTest= new BTraceTest(); BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); for (int i = 0; i < 10; i++) { reader.readLine(); int a = (int)Math.round(Math.random()*1000); int b = (int)Math.round(Math.random()*1000); System.out.println(traceTest.add(a,b)); } }}

java

Java List实现group by

一般情况下我们可能很熟悉在数据库中使用group by来分组一些数据,但是如果数据来源不是数据库的话可能就需要通过在代码中实现group by了 例子:比如有一组书Book的集合,我们要按照书的类型(type)分组 12345678910111213package org.xuan;import lombok.AllArgsConstructor;import lombok.Data;@Data@AllArgsConstructorpublic class Book { private String name; private String type; private double price;} 增加几本书到list 123456789List <Book> bookList =Arrays.asList( new Book("java programming","java",123.1D), new Book("java in concurrency","java",123.2D), new Book("c++ primary","c++",123.3D), new Book("groovy in action","groovy",123.4D), new Book("effective java","java",123.5D), new Book("jvm in practice","java",123.6D), new Book("scala in action","scala",123.7D) );

java

Java NIO创建步骤

NIO创建过程一、打开ServerSocketChannel,用于监听客户端的连接 1ServerSocketChannel acceptSvr = ServerSocketChannel.open(); 二、绑定监听端口,设置连接为非阻塞模式 12acceptSvr.socket().bind(new InetSocketAddress(InetAddress.getByName("IP"),port));accptSvr.configureBlocking(false); 三、创建Reactor线程,创建多路复用器并启动线程 12Selector selector = Selector.open();new Thread(new ReactorTask()).start();

java

Java工程师(后端)技能树

我的Java技能树点亮之路 编程思想脱离于语言之上的一些不变的知识 设计模式,重构,Clean Code ,代码大全,Unix编程艺术 算法导论什么的就算了,但是至少得学会实现《数据结构》上的集中最基本的数据结构,java实现 理解 SOA面向服务架构 工具加成让自己的开发工具从小刀变成 Linux &shell &vim Ngix 工具类 google guava, apache-commons 构建工具maven,gradle Web容器 tomcat 版本控制git java8新特性 mysql&mariadb 数据库进阶,慢查询,数据库引擎,索引 熟悉Http,《图解HTTP》 了解使用noSql,mongodb

java

Java内存模型【译】

本文翻译自 Java Memory Model旨在加深自己对Java Memory Model (JMM)的理解。 The Java memory model specifies how the Java virtual machine works with the computer’s memory (RAM).The Java virtual machine is a model of a whole computer so this model naturally includes a memory model - AKA the Java memory model.It is very important to understand the Java memory model if you want to design correctly behaving concurrent programs.The Java memory model specifies how and when different threads can see values written to shared variables by other threads, and how to synchronize access to shared variables when necessary.The original Java memory model was insufficient, so the Java memory model was revised in Java 1.5. This version of the Java memory model is still in use in Java 8. Java内存模型详述了java虚拟机如何与物理机的RAM的一起工作的,java虚拟机是整个计算机的模型,所以这个模型自然包括内存模型,这个模型卡就是Java内存模型。如果你想正确的设计并发程序,知道Java内存模型是非常重要的java内存模型详解了多个不同的线程是何时而又如何写入一个共享的变量的,还有如何同步的访问一个共享变量。原来的Java内存模型是不足的,所以Java内存模型在java 5中重新修订了,这个版本的java内存模型一直在Java8中还在使用。 内部的java内存模型 The Java memory model used internally in the JVM divides memory between thread stacks and the heap. This diagram illustrates the Java memory model from a logic perspective:

java

Java集合中的Fail-fast和Fail-Safe机制

1.何为Fail-fast和Fail-Safe机制?java.util包里的Iterator 抛出 ConcurrentModificationException异常, 在集合迭代的时候被集合的add方法或者 remove方法调用。fail-fast 指java的集合的一种错误机制,当多个线程对集合修改操作的时候就可能抛出ConcurrentModificationException异常。 java.util.concurrent包里的Iterator 通过迭代一个集合的snapshot 允许并发修改集合,但是在迭代器创建之后可能不反映Collection更新。fail-safe机制意味着多个线程在操作同一个集合的时候,不会出现ConcurrentModificationException异常,但是需要复制集合获得集合的快照,所以性能上开销会比非同步的集合开销要大。 多线程环境下用java.util.concurrent包里的集合替代 java.util包里的集合,比如 CopyOnWriteList=>ArrayList,ConcurrentHashMap=>HashMap etc. 2.JDK中的源码分析下面代码是JDK1.7源码中ArrayList中的ListIterator,当Iterator创建时,当前的计数器modCount 赋值给Iterator对象,注意到modCount是一个 transient类型的成员变量,transient说明了计数器将不被序列化。 protected transient int modCount = 0; modCount用来记录List修改的次数的计数器,每修改一次(添加/删除等操作),将modCount+1,例如 add()方法: 1234567public void add(int index, E element) { rangeCheckForAdd(index); checkForComodification(); l.add(index+offset, element); this.modCount = l.modCount; size++; }

java
12

本站由 Hank Zhao 使用 Stellar 主题创建。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。
本站总访问量