基本类型
- byte 8位整数,-128~127
- short 16位整数,-32768~32767
- int 32位
- long 64位,为了标识,建议跟个后缀L或l。
- float 32位浮点小数,有一个后缀F/f,没有后缀的浮点数默认为double类型。
- double 64位浮点小数,后缀D/d。
- char 字符型
boolean 布尔型
只有很少的情况适用float,例如,需要快速地处理单精度数据,或者需要存储海量数据。否则都是使用double。
- Java整型和浮点数都是有符号数,不存在有符号数和无符号数比较或运算时出错的情况。
限定符
- 对类、接口及其成员进行声明时,public表示可以被任何人访问
- protected只能被本包的本类和位于任何包的子类访问
- default只能被本包访问
- private只能被本类访问
- 重载可以改变方法的访问范围,但只能变大。
final
- 一个final类不能有子类,一个final的field表示它是一个常量。
- 一个final域需要在对象调用构造器后就被初始化,不接受默认初始化,因此定义了final常量后要么顺便赋个值给它,要么在构造器里给它赋值。
把方法的入参定义为final的话,该参数不可以被重新赋值。可以防止在方法里面不小心改变了不能变的参数,造成一些不必要的麻烦。
public static void printAll(final Curry temp){ //实参传进来给形参,就相当于初始化完成 temp.setSmallName("fk do it"); System.out.println(temp.getSmallName()); temp = new Curry(); 传送进来的Curry引用是final,不可以再赋值了,这里一定会报错哦! }
static
- 一个static的field表明它是属于类的,而不是每一个对象都单独拥有一份的。
- 类加载的时候将static变量初始化(接受默认初始化)并加载到方法区,因此它是随着类的加载而加载的
- 一个static的final常量由于不能被默认初始化,所以类加载的时候若它还未人为初始化则编译报错。因此静态常量需要定义即赋值或在静态代码块中赋值(构造器不随类加载而执行,而是随着对象创建而被调用的),或者像笔记:hibernate学习之Crud->封装Util获取session工厂一样,让final常量=一个静态方法的返回值,强制类加载时也把静态方法执行了。反正必须让它在类加载时完成初始化。
- 静态方法则不会随着类的加载而执行,但静态代码块是随着项目的开始而执行的。
native
- native修饰某个方法表明该方法实现的文件是由其他语言(C/C++等)写的。
Array.length
- 数组的求长度(总容量)属性length是java.lang.reflect.Array中的一个属性,该属性由getLength(Object array)方法赋值,但这个方法是由其他语言来实现的,因为要接触到底层,而java语言本身是不接触 及其底层的。
数组
- 声明一个父类数组,其中可以放子类对象,但是这些对象就被隐转成父类,只有父类的成员了。
- 用instanceof能检测出元素的原类型
定义基本类型数组,声明后即可放入元素
int[] a=new int[5]; a[0]=0;
定义元素为类的数组,声明后还要对每个元素都new一遍,否则元素全部为空指针
Bag<Integer>[] adj=(Bag<Integer>[])new Bag[V]; //不能创建泛型指定类型的泛型数组,只能先创建泛型数组再强转 //这一步不能省略,必须一个个分配Bag,否则adj数组中每个元素都是空指针 for(int i=0;i<V;i++){ adj[i]=new Bag<Integer>(); adj[i].add(i); //不经过上一行的话报空指针异常 }
父类强转为子类
- 可以的,但此父类对象必须原本就是由子类对象转来的。
- 例如,Father father=new Son()或Father father=(Father)son;
转换前可以先用instanceof检查
if(father instanceof Son){ Son son=(Son)father; }
- 其实子类转为父类(隐式或强制),比父类多的成员只是暂时不能访问,被隐藏了而已,被转回来之后又能访问了。
构造方法不能继承
- 如果父类中有无参构造函数,创建子类时,必须在构造函数第一行调用父类的无参构造函数;如果父类只定义了有参构造函数,那么编译器无法隐式加上无参构造函数,而子类又需要调用无参构造函数,故编译报错。当然,如果子类需要的只是父类的有参构造函数,那么调用即可。编译器不会因为父类缺少无参构造函数而报错。
同父类强转在编辑时检测不到异常
- 编译时才能发现类型不能强制的错误,并且抛异常,所以不要以为强转时没飘红就是可以了,只是检测不出来而已。
collection.toArray()
- list.toArray(): 将list(或其他集合如Set)转为Object[]。
String[] array= (String[]) list.toArray();
- 以上代码运行报错:Exception in thread “main” java.lang.ClassCastException:
[Ljava.lang.Object; cannot be cast to [Ljava.lang.String;原因是不能将Object[]直接转为String[],只能遍历每一个元素进行转化。 - Java中的强制类型转换只针对单个对象,不能将整个数组转换为另一类型,这和数组初始化时需要一个个来是类似的。
- 正解:
Object[] arr = list.toArray();
for (int i = 0; i < arr.length; i++) {
String e = (String) arr[i];
}
- list.toArray(T[] a): 转化为指定类型数组,比上个方法更好用。
predicates.toArray(new Predicate[0]); // toArray(数组):将调用方法的对象转换为数组,
// 并存储到传入的数组中;若数组空间不足则重新创造一个数组并返回
predicates.toArray( new Predicate[predicates.size()] );
线程
synchronized:Java 关键字,当它用来修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码。
//该方法是产生一个double型的Gaussian随机数 public synchronized double nextGaussian(){ }
获取当前类名
- this.getClass().getName()
- Thread.currentThread().getStackTrace()[1].getClassName()
System.currentTimeMillis()获取当前时间
获取当前的时间,new Date()底层调用的也是这个
long startTime= System.currentTimeMillis();//返回一个long型,保存到数据库转为date展示(Date原本也是用秒数表示的)
获取文件后缀名
File file = new File("HelloWorld.java");
String fileName = file.getName();
String suffix = fileName.substring(fileName.lastIndexOf(".") + 1);
测试程序运行时间
在程序开始前记录一次当前时间,程序结束时再记录一次,两者相减即可
long startTime = System.currentTimeMillis(); ---待测试程序--- long endTime = System.currentTimeMillis(); System.out.println("运行时间:" + (endTime - startTime) + "ms");
System.nanoTime()
返回纳秒(即当前与某个时间基准的时间差),1ms=1ns10001000,中间还隔了个微秒。
long time1=System.nanoTime();
只用于计算时间差,不要用于计算距离现在的时间差,因为纳秒太小了
//计算程序运行时间 long time1=System.nanoTime(); for(int i=0;i<200;i++){ System.out.print("."); } long time2=System.nanoTime(); System.out.println(time2-time1);
参数类型后加…
- test(ObjectA… objectAs)可变长度参数列表,表示这个类型的入参可以有0个或多个ObjectA或ObjectA[],传参时可以是一个个并列地传,也可以是直接一个数组。
方法内对它们的遍历:
public void correlationRoles(Long... roleIds) { for(Long roleId : roleIds) { } //or for(int i=0;i<roleIds.length;i++){ } }
如果调用时什么也没传,那么该参数的长度为0。
- 必须放在最后一个形参的位置上,否则报错。
- 假如已有一个方法test(String… strings),那么还可以写方法test(),而当我们调用test()时,编译器优先匹配test()方法,没有test()时才会匹配test(String… strings);
- 但是不能写test(String[] strings),编译出错,系统提示出现重复方法。
Clazz
- 为什么很多程序员喜欢用Clazz命名?
- 它表示类的意思,因为Class已经被作为关键字,人们不能再使用,因此用clazz作为代替。
Deque类
- 即double ended queue,双端队列,继承自Queue,是一种具有队列和栈的性质的数据结构。元素可以从两端弹出,插入和删除都可以在两端进行。
- push(): 向队头插入元素。
- pop(): 弹出队头元素。
- removeFirst(): 弹出首元素,如果是作为栈来使用则应该是最后一个进去的元素。
- removeLast(): 弹出尾元素。
- 参考文章
- 代码示例:ideaProjects/shiro-chapter18/web/shiro/filterKickoutSessionControllerFilter;不知道为什么在这里removeFirst()弹出的是队尾元素,removeLast()反而是队头。
StringUtils
- hasText(str): 字符串判空,如果字符串为null、””或” “,那么返回false。