您的位置:首页 > 编程语言 > Java开发

初探JAVA小知识点(1)

2017-03-06 22:10 141 查看
  今天整理几个java的小知识点,包括static的作用,final的作用,for each循环的原理以及transient的作用。

首先是static

1. static的在java中用的最多的就是静态变量和静态方法,例如
public class StaticExample {
public static int NUM = 0;

public static int getNum() {
return NUM;
}

public static void main(String[] args) {
NUM = 1;
System.out.println(getNum());
}
}


这个相信大家都知道,变量NUM和方法getNum()就直接依赖于StaticExample这个类,而不用new一个StaticExample的实例出来。

2. 再一个用的比较多的就是静态代码块

public class StaticExample {
public static int NUM = 0;

public static int getNum() {
return NUM;
}

static {
System.out.println("hello static");
}

public static void main(String[] args) {
NUM = 1;
System.out.println(getNum());
}
}


在static块内部的代码会在类加载的时候运行,适合做一些初始化的工作

3.static 另外一个用的很少的功能是,静态内部类,反正我到现在没有主动用过,和普通内部类的区别就是访问一个普通内部类类需要先new一个对象出来,例如classA有一个内部类classB,classA a = new classA(),然后classB b = new a.classB();才能访问,而如果是静态内部类,只需要classB b = new ClassA.classB(),就可以访问了。

同时非静态类不可以有静态成员,而静态类可以有静态成员,非静态类可以访问外部类的非静态成员,而静态类就不可以,这个目前在工作中没有怎么用到过

4. static 类另一个使用的非常非常少,我也是无意间看到的一个功能就是静态导包。

import static java.lang.System.out;

public class StaticExample {
public static int NUM = 0;

public static int getNum() {
return NUM;
}

static {
System.out.println("hello static");
}
int tt = 0;

public static void main(String[] args) {
NUM = 1;
System.out.println(getNum());
out.println("hello import static");
}
}


就是上面的使用方法,没有get到这种用法的精髓,对于常年使用ide的人来说,简直是多此一举。

然后是final

final关键字的主要作用就是表明是不可修改的。final 修饰类时,表明这个类时不能被继承的,final修饰方法时表示这个类是不能被子类重写的,final修饰变量时,表明该变量时不能被重新赋值的,注意对于基本类型,就是值不能变,而对于一个对象的实例而言,仅仅是对象的引用不能变,而对象里面的值是可以变化的。目前在我的工作中,基本就是用final来定义一些常量,一些资料里介绍,使用final除了不变性以外,很重要的就是JVM会对final做优化,可以提升效率,这个没有测试过。

比较有意思的是for each

平常for each用的挺多的,也知道for each内部用的是iterator,但是没有研究过细节,后来无意中写了一行让我不是很能理解的代码,稍微研究了下。

代码类似下面

import java.util.ArrayList;
import java.util.List;

public class FinalExample {

    
    
    public static void main(String[] args) {
        List<String> stringList = new ArrayList<String>();
        stringList.add("hello");
        stringList.add("world");
        stringList.add("java");
        stringList.add("is");
        stringList.add("great");
        for(String tempString : stringList){
            if(tempString.equals("is")){
                stringList.remove(tempString);
            }
        }
    }

}


当时我的第一反应肯定是运行会报java.util.ConcurrentModificationException,但是实际运行后竟然没有报错,这不科学啊,for each循环的时候是不能进行remove操作的啊。

当时纠结了好一会儿,后来网上百度一下,加看下源码终于弄懂了。

public boolean hasNext() {
return cursor != size;
}

@SuppressWarnings("unchecked")
public E next() {
checkForComodification();
int i = cursor;
if (i >= size)
throw new NoSuchElementException();
Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length)
throw new ConcurrentModificationException();
cursor = i + 1;
return (E) elementData[lastRet = i];
}

public void remove() {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification();

try {
ArrayList.this.remove(lastRet);
cursor = lastRet;
lastRet = -1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}


for each主要就是通过collection内部的hasNext()和next()来进行循环取值的,在remove时,报错的其实是
if (i >= elementData.length)
throw new ConcurrentModificationException();


多remove几个以后就会发现,只有remove倒数第二个的时候不会报错,其他时候就会报错。

为什么倒数第二个被remove不会报错呢?因为倒数第二个,remove以后size变为原先的maxSize-1,这时候hasNext()函数中,cursor已经和size相等了,然后就跳出循环,不走next()函数了,实际上最后一个元素并没有被遍历到。

最后一个是transient

这个主要是用于在序列化的时候,声明某个属性不能被序列化,比如一个叫User的class,里面有一个属性叫password,密码这个属性不希望被序列化,那么就在前面加一个transient就好了。

今天就先写到这里了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息