
- 显式定义一个private static final long serialVersionUID且不要轻易修改这个值(达到向下兼容的目的)
- 使用transient修饰的变量,在序列化的时候会忽略他的值,在反序列化的时候会将其值设为初始值,int为0,引用类型为null
class Data implements Serializable {
private static final long serialVersionUID = -1018436805097712788L;
private int n;
public Data(int n) { this.n = n; }
@Override
public String toString() { return Integer.toString(n); }
}
class Worm implements Serializable {
public static void main(String[] args)
throws ClassNotFoundException, IOException { // 序列话读入和写入Object可能会有这两个异常
// 将你要序列化的object,保留到一个文件中
Random rand = new Random();
Data d = new Data(rand.nextInt(10)); //构建你需要序列话的Object
System.out.println("d = " + d);
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("worm.out")); // 准备写入的文件
out.writeObject(d);
out.flush();
out.close(); // 执行到这里你可以看见worm.out这个文件,
// 以下的代码读出你刚刚写入Object
ObjectInputStream in = new ObjectInputStream(new FileInputStream("worm.out")); // 读你刚刚写入的文件
Data d2 = (Data)in.readObject(); // 重新构建你刚刚写入的Object
System.out.println("d2 = " + d2);
}
}
8.static 关键字
- 使用static修饰的可以是变量,代码块,内部类,方法
- 某个类被加载之后调用以上被static修饰的代码的顺序是:
- 父类的静态代码块(若有多个,从上到下)
- 子类的静态代码块(若有多个,从上到下)
(上面两部只有类第一次初始化的时候会执行) - 父类的成员变量初始化
- 父类的初始化代码块(若有多个,从上到下)
- 父类的构造函数
- 子类的成员变量初始化
- 子类的初始化代码块(若有多个,从上到下)
- 子类的构造函数
- 总结:在第一次加载某个类时,先加载父类的静态代码块;实例化的时候先加载父类的成员变量、初始化代码块、构造函数,再加载子类的
class StaticExample {
public StaticExample() {
System.out.println("hello");
}
//static block
static{
//can be used to initialize resources when class is loaded
System.out.println("StaticExample static block");
//can access only static variables and methods
str="Test";
setCount(2);
}
//multiple static blocks in same class
static{
System.out.println("StaticExample static block2");
}
//static variable example
private static int count; //kept private to control it's value through setter
public static String str;
public int getCount() {
return count;
}
//static method example
public static void setCount(int count) {
if(count == 0)
StaticExample.count = count;
}
//static util method
public static int addInts(int i, int...js){
int sum=i;
for(int x : js) sum+=x;
return sum;
}
//static class example - used for packaging convenience only
public static class MyStaticClass{
public int count;
}
}
class TestStatic {
public static void main(String[] args) {
StaticExample.setCount(5);
//non-private static variables can be accessed with class name
StaticExample.str ="abc";
StaticExample se = new StaticExample();
System.out.println(se.getCount());
//class and instance static variables are same
System.out.println(StaticExample.str +" is same as "+se.str);
System.out.println(StaticExample.str == se.str);
//static nested classes are like normal top-level classes
StaticExample.MyStaticClass myStaticClass = new StaticExample.MyStaticClass();
myStaticClass.count=10;
StaticExample.MyStaticClass myStaticClass1 = new StaticExample.MyStaticClass();
myStaticClass1.count=20;
System.out.println(myStaticClass.count);
System.out.println(myStaticClass1.count);
}
}
最后执行的结果 StaticExample static block StaticExample static block2 hello 0 abc is same as abc true 10 209.注解
- 元注解有6个:
- @Target:表示这个注解用在什么地方
- @Retention:保留策略,有SOURCE,CLASS,RUNTIME
- @Dcoumented:将此注解保留在javadoc中
- @Inherited:是否可以被继承
- @Repeatable:是否允许一个注解在一个元素上出现多次
- @Native:修饰成员变量,表示成员变量可以被本地代码使用
- 自定义注解
- 注解与反射的结合
//获取一个类上的注解信息
//关键方法:isAnnotationPresent判断是否存在注解
// getAnnotation获得注解
Class> clz = bean.getClass();
Method[] methods = clz.getMethods();
for (Method method : methods) {
if (method.isAnnotationPresent(EnableAuth.class)) {
String name = method.getAnnotation(EnableAuth.class).name();
}
}
10.泛型
- 定义:泛型是JDK5引入的一个新特性,允许在定义类和接口的时候使用类型参数。声明的参数类型在调用时传入具体的类型。常用于集合类型框架中。最大的好处就是提高代码的复用性,如需要在List中放Integer,String,使用泛型只需要定义一个公共的接口
- 泛型擦除:指的是在编译的时候将泛型去掉,最终留下最基本的原生类型,如方法重载是基于泛型的话,在编译的时候会进行泛型擦除,导致编译报错
public class GenericTypes {
public static void method(List list) {
System.out.println("invoke method(List list)");
}
public static void method(List list) {
System.out.println("invoke method(List list)");
}
}
- 泛型中K T V E Object等的作用E - Element (在集合中使用,因为集合中存放的是元素)
- 限定通配符和非限定通配符
- 上界: extends T> 类型必须为T类型或其子类
- 下界: super T> 类型必须为T类型或其父类
- 泛型必须使用限定内的类型进行初始化,否则会编译出错
- 非限定通配符表示可以使用任意泛型类型来代替
- extends 和 super的用法,在使用泛型时,存取元素时用super,获取元素时,用extends。频繁往外读取内容的,适合用上界Extends。经常往里插入的,适合用下界Super。
public class Food {}
public class Fruit extends Food {}
public class Apple extends Fruit {}
public class Banana extends Fruit{}
public class GenericTest {
public void testExtends(List extends Fruit> list){
//报错,extends为上界通配符,只能取值,不能放.
//因为Fruit的子类不只有Apple还有Banana,这里不能确定具体的泛型到底是Apple还是Banana,所以放入任何一种类型都会报错
//list.add(new Apple());
//可以正常获取
Fruit fruit = list.get(1);
}
public void testSuper(List super Fruit> list){
//super为下界通配符,可以存放元素,但是也只能存放当前类或者子类的实例,以当前的例子来讲,
//无法确定Fruit的父类是否只有Food一个(Object是超级父类)
//因此放入Food的实例编译不通过
list.add(new Apple());
// list.add(new Food());
Object object = list.get(1);
}
}
- List> 是一个未知类型的List,而List 其实是任意类型的List。你可以把List, List赋值给List>,却不能把List赋值给 List。
Regarding List11.错误和异常
- https://blog.csdn.net/m0_37602175/article/details/80271647
- Error和Exception继承自Throwable类,异常指的是在程序中可能出现并且应该被捕获的情况(分为受检异常和非受检异常,非受检异常又称为运行时异常),Error指的是不大可能出现的情况,不便于也不需要进行捕获。
- 正确处理异常:将异常的范围尽可能地缩小,捕获异常之后进行相应的处理(自己处理或向上抛给调用者)
- try{}catch{}finally中
-
- 如果try{}里有return,会在执行finally之前将返回变量的内存地址复制一份,最后返回的是复制好的这份地址
-
- finally里面对return的变量做了修改,如果是基本数据类型,直接 *** 作值,即使修改了,return的值还是原来的值
-
- finally里面对return的变量做了修改,如果是引用数据类型,复制的是对象的地址,修改了,return的值指向修改后的值,所以最终会表现出被修改
-
Instant: 时间戳
-
Duration: 持续时间, 时间差
-
LocalDate: 只包含⽇期, ⽐如: 2016-10-20
-
LocalTime: 只包含时间, ⽐如: 231210
-
LocalDateTime: 包含⽇期和时间, ⽐如: 2016-10-20 231421
-
Period: 时间段
-
ZoneOffset: 时区偏移量, ⽐如: +8:00
-
ZonedDateTime: 带时区的时间
-
Clock: 时钟, ⽐如获取⽬前美国纽约的时间
//获取当前日期
LocalDate today = LocalDate.now();
int year = today.getYear();
int month = today.getMonthValue();
int day = today.getDayOfMonth();
System.out.printf("Year : %d Month : %d day : %d t %n", year,month, day);
//获取指定日期
LocalDate date = LocalDate.of(2018, 01, 01);
//判断闰年
LocalDate nowDate = LocalDate.now();
boolean leapYear = nowDate.isLeapYear();
//获得两个时间之间的差值
Period period = Period.between(LocalDate.of(2018, 1, 5),LocalDate.of(2018, 2, 5));
//输出0
System.out.println(period.getDays());
14.并发和并行
并行-两个线程再两个CPU上同时运行互不干扰;并发-某个时间段有多个线程运行,看起来是同时运行的,但细化到某个时刻,还是串行执行的
15.Unicode 和 GBK- Unicode是一个字符集,定义和ASCIi(只包含了256个字符)相同,Unicode虽然定义了编码方式,但是没有定义如何进行存储。而utf-8和utf-16是对于Unicode编码的存储规范(Unicode Transformation Format),最常用的utf-8使用可变存储长度的方案,英文字符使用一个字节进行存储,大部分汉字使用3个字节进行存储
- GBK是国内的字符集通用标准
- URL解编码:RFC标准规定只有字母和数字[0-9a-zA-Z]、一些特殊符号“$-_.+!*’(),”[不包括双引号]、以及某些保留字,才可以不经过编码直接用于URL;除此以外的其他字符在转化为url的过程中会经过编码。关于URL编码的博客
- 首先明确是对象
- 不能使用==,使用equals会比较精度,使用copareTo()不会比较精度
(parameters) -> expression
或
(parameters) ->{ statements; }
包含了以下4个关键特征:
1. 可选的参数圆括号,一个参数无需定义圆括号,多个参数需要定义圆括号
2. 可选的大括号,如果主体包含了一个语句,则不需要大括号
3.可选的返回关键字,如果主体只有一个表达式返回值,则编译器会自动返回值,大括号需要指定表达式返回了一个数值
4.可选的类型声明,不需要声明参数类型,编译器可以统一识别参数类型
// 1. 不需要参数,返回值为 5 () -> 5 // 2. 接收一个参数(数字类型),返回其2倍的值 x -> 2 * x // 3. 接受2个参数(数字),并返回他们的差值 (x, y) -> x – y // 4. 接收2个int型整数,返回他们的和 (int x, int y) -> x + y // 5. 接受一个 string 对象,并在控制台打印,不返回任何值(看起来像是返回void) (String s) -> System.out.print(s)
菜鸟教程关于lambda表达式的介绍
18.Stream - 简介- Stream提供了一种声明的方式处理数据(?)
- Stream提供一种类似于SQL查询的方式对Java集合和运算,将集合抽象为管道,在管道上的节点对集合进行 *** 作
- 不是一种数据结构,是数据源的一个视图
- 函数式编程,对Stream的 *** 作不会修改原来的数据,而是会产生一个新的Stream
- 惰式执行,对Stream的 *** 作不会立即执行,需要时才会执行
- Stream只能被消费一次,一旦执行完全就会失效,想要结果需要重新执行
List2. 使用Stream类的方法直接创建流strings = Arrays.asList("Hollis", "HollisChuang", "hollis", "Hello", "HelloWorld", "Hollis"); Stream stream = strings.stream();
Stream- 中间 *** 作 1. filter: filter items according to a given predicatestream = Stream.of("Hollis", "HollisChuang", "hollis", "Hello", "HelloWorld", "Hollis");
List2. map: processes items and transformstrings = Arrays.asList("Hollis", "", "HollisChuang", "H", "hollis"); strings.stream().filter(string -> !string.isEmpty()).forEach(System.out::println); //Hollis, HollisChuang, H, hollis
List3. limit: limit the resultsnumbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5); numbers.stream().map(i -> i*i).forEach(System.out::println); //9,4,4,9,49,9,25
List4. sorted: sorted items inside streamnumbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5); numbers.stream().limit(4).forEach(System.out::println); //3,2,2,3
List5. distinct: remove duplicate items according to equals methodnumbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5); numbers.stream().sorted().forEach(System.out::println); //2,2,3,3,3,5,7
List3.最终 *** 作 - forEach(): for each item, outputs somethingnumbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5); numbers.stream().distinct().forEach(System.out::println); //3,2,7,5
Random random = new Random(); random.ints().limit(10).forEach(System.out::println);- count(): counts currrent items
List- collect(): reduce the stream into a desired collectionstrings = Arrays.asList("Hollis", "HollisChuang", "hollis", "Hollis666", "Hello", "HelloWorld", "Hollis"); System.out.println(strings.stream().count()); //7
Liststrings = Arrays.asList("Hollis", "HollisChuang", "hollis","Hollis666", "Hello", "HelloWorld", "Hollis"); strings = strings.stream().filter(string -> string.startsWith("Hollis")).collect(Collectors.toList()); System.out.println(strings); //Hollis, HollisChuang, Hollis666, Hollis
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)