7-18

7-18,第1张

7-18 7.序列化和反序列化 序列化和反序列化最常用的方式是将某个类实现Serializable接口,使用对象流进行相应的序列化和反序列化 重点需要注意的是
  • 显式定义一个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修饰的代码的顺序是:
  1. 父类的静态代码块(若有多个,从上到下)
  2. 子类的静态代码块(若有多个,从上到下)
    (上面两部只有类第一次初始化的时候会执行)
  3. 父类的成员变量初始化
  4. 父类的初始化代码块(若有多个,从上到下)
  5. 父类的构造函数
  6. 子类的成员变量初始化
  7. 子类的初始化代码块(若有多个,从上到下)
  8. 子类的构造函数
  • 总结:在第一次加载某个类时,先加载父类的静态代码块;实例化的时候先加载父类的成员变量、初始化代码块、构造函数,再加载子类的
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
20
9.注解
  • 元注解有6个:
  1. @Target:表示这个注解用在什么地方
  2. @Retention:保留策略,有SOURCE,CLASS,RUNTIME
  3. @Dcoumented:将此注解保留在javadoc中
  4. @Inherited:是否可以被继承
  5. @Repeatable:是否允许一个注解在一个元素上出现多次
  6. @Native:修饰成员变量,表示成员变量可以被本地代码使用
  • 自定义注解
使用@interface
  • 注解与反射的结合
//获取一个类上的注解信息
//关键方法: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 (在集合中使用,因为集合中存放的是元素)
1. T - Type(Java 类) 2. K - Key(键) 3. V - Value(值) 4. N - Number(数值类型) 5. ? - 表示不确定的java类型(无限制通配符类型) 6. S、U、V - 2nd、3rd、4th types 7. Object - 是所有类的根类,任何类的对象都可以设置给该Object引用变量,使用的时候可能需要类型强制转换,但是用使用了泛型T、E等这些标识符后,在实际用之前类型就已经确定了,不需要再进行类型强制转换。
  • 限定通配符和非限定通配符
  1. 上界: 类型必须为T类型或其子类
  2. 下界: 类型必须为T类型或其父类
  3. 泛型必须使用限定内的类型进行初始化,否则会编译出错
  4. 非限定通配符表示可以使用任意泛型类型来代替
  5. 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 list){

        //报错,extends为上界通配符,只能取值,不能放.
        //因为Fruit的子类不只有Apple还有Banana,这里不能确定具体的泛型到底是Apple还是Banana,所以放入任何一种类型都会报错
        //list.add(new Apple());

        //可以正常获取
        Fruit fruit = list.get(1);
    }

    public void testSuper(List 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 List not accepting a List, that makes sense because a String is not Object; it is a subclass of Object. The fix is to declare public static void test(List set) .... But then the extends Object is redundant, because every class directly or indirectly extends Object.
 
11.错误和异常 
  • 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的值指向修改后的值,所以最终会表现出被修改
13.时间 针对Java8之前时间API的设计差,Java8之后引入了新的时间包,新的时间及⽇期API位于java.time包中
  • 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编码的博客
16.BigDecimal的使用
  • 首先明确是对象
  • 不能使用==,使用equals会比较精度,使用copareTo()不会比较精度
17.lambda表达式 - lambda表达式也称为闭包,允许把一个函数作为参数传递到方法中,作用是使得代码更加的紧凑简洁
(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只能被消费一次,一旦执行完全就会失效,想要结果需要重新执行
- 使用 - 对于流的 *** 作有3步,流的创建、中间 *** 作、最终 *** 作 - 创建 1. 基于原有集合类的增强,为原有的集合类添加stream方法
List strings = Arrays.asList("Hollis", "HollisChuang", "hollis", "Hello", "HelloWorld", "Hollis");
Stream stream = strings.stream();

2. 使用Stream类的方法直接创建流
Stream stream = Stream.of("Hollis", "HollisChuang", "hollis", "Hello", "HelloWorld", "Hollis");
- 中间 *** 作 1. filter: filter items according to a given predicate
List strings = Arrays.asList("Hollis", "", "HollisChuang", "H", "hollis");
strings.stream().filter(string -> !string.isEmpty()).forEach(System.out::println);
//Hollis, HollisChuang, H, hollis

2. map: processes items and transform
List numbers = 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

3. limit: limit the results
List numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5);
numbers.stream().limit(4).forEach(System.out::println);
//3,2,2,3
4. sorted: sorted items inside stream
List numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5);
numbers.stream().sorted().forEach(System.out::println);
//2,2,3,3,3,5,7
5. distinct: remove duplicate items according to equals method
List numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5);
numbers.stream().distinct().forEach(System.out::println);
//3,2,7,5
3.最终 *** 作 - forEach(): for each item, outputs something
Random random = new Random();
random.ints().limit(10).forEach(System.out::println);
- count(): counts currrent items
List strings = Arrays.asList("Hollis", "HollisChuang", "hollis", "Hollis666", "Hello", "HelloWorld", "Hollis");
System.out.println(strings.stream().count());
//7
- collect(): reduce the stream into a desired collection
List strings = 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

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/4670828.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-11-07
下一篇 2022-11-06

发表评论

登录后才能评论

评论列表(0条)