- 显式定义一个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(Listlist) { 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条)