目录

java水平提升记录

以下是我不熟的

  1. try with resource:

    • 语法格式:try( Scanner scanner=new Scanner){ // scan } finally {scanner.close();}
      • 不写catch。 编译器会自动在finally里面加 变量.close()
      • 语法糖
    • 需要对象本身实现了 java.lang.AutoCloseable
    • 优点: 比使用finalize 回收对象更可控
  2. 构造函数赋值: 使用双花括号可以实现类似 with的效果,不用写 this.

    • 语法格式: Person = new Person(){{ name = 'abc'; age=11;}}
    • 用途: 针对没有相应构造函数,但是又要赋值的情况。
  3. 内部类:

    • 定义和声明:把一个类的声明 class InnerExample 放到另外一个类里面
      • 编译器会生成 xxx$xxx 这样的class文件
      • 内部类不能和外部类重名
    • 使用:
      • 在封装内部类的内部使用跟其他普通类没差别
      • 在其他地方使用:
        • 类名前要冠以外部类的名字
        • 在用new创建内部类的时候,也要在new 前面冠以对象变量: 外部对象名.new 内部类名(参数)
    • 注意:
      • 内部类可以访问外部类的字段和方法,即使private的也可以
      • 当内部类中有和外部类同名的字段或方法,可以用 外部类名.this.字段及方法
      • 内部类可以用public protected,private 修饰符,外部类只能用public或者默认
      • 内部类可以用 final, abstract 修饰符
      • 用static修饰符定义内部类的时候,它实际被声明成为了外部类(有人认为这是嵌套类)
      • 当使用static类的时候:
        • 实例化的时候,new签名不需要对象实例变量(因为static跟实例无关)
        • static类中不能访问其外部类的非static字段和方法,只能访问static成员
        • static方法中不能访问非static的域及方法,也不能不带前缀地new 一个非static的内部类
  4. 局部类(在方法里面定义的类 local class)

    • 注意:
      • 不能用public private protected static修饰
      • 可以用final 或者abstract修饰
      • 可以访问其外部类的成衣
      • 不能访问局部变量,除非它是final的
  5. 匿名类: 一种特殊的内部类(anonymous class)

    • 定义:
      • 定义和创建同时使用和完成,类的定义前面有一个new
        • new 类名 或接口名 (){......}
        • 不使用关键字class,也不使用extends 及 implements
      • 不取名字,直接用其父类或接口的名字,该类是父类的子类,或者实现了一个接口
      • 编译器生成 xxxxx$1 之类的名字
      • 在构造对象的时候使用父类构造方法
    • 典型应用:
      1. 界面的事件处理:
        1. uiObj.addActionListener(someAction)
        2. uiObj.addActionListener(new ActionListener(){ public void actionPerformed(Event e){ /事件处理代码/ } });
      2. 作为方法的参数:eg排序,实现一个比较大小的接口
        1. Arrays.sort(books, new Comparator(){ public int compare(Book b1, Book b2){ return b1.price - b2.price; } });
    • 类似闭包
  6. Lambda表达式:

    • 信息:Lambda expression.
      • 大体上相当于其他语言的"匿名函数" 或 "函数指针"
      • java中他实际上是"匿名类的一个实例"
    • 写法: (参数)->结果
    • eg:
      • (String s) -> s.length()
      • () -> { System.out.println("abc"); }
      • x -> x*x
      • 求积分例子: double d = Integra( x-> Math.sin(x), 0, Math.PI, 1e-5);
    • 意义:
      • Lambda表达式大大简化了书写:线程,积分函数,按钮事件处理 等等
    • 限制:
      • 能写成 Lambda表达式的接口 要求 **包含且最多只能有一个 ** 抽象函数
      • 这样的接口可以(但不强制)用注记:
    • 总结:
      • Lambda表达式 是 接口 或者 接口函数的简写
  7. 高级语法:装箱,枚举,注解

    • 信息:从JDK 1.5开始增加的一些新的语法糖
      • 基本类型的包装类:将基本类型(Primitive type )包装成 Object(引用类型)
      • 共8类:Boolean, Byte, Short, Character, Integer, Long, Float, Double
    1. 装箱(Boxing)和拆箱(Unboxing)
      • 把基本类型直接赋值给引用类型 Integer I = 10; int i=I;
        • 翻译为: Integer I = Integer.valueOf(10); Object [] ary = {1, "aaa};
    2. 枚举(enum) 是一种特殊的class类型
      • 写法: enum Lignt {Red, Yellow, Green}; , Light light = Light.Red;
      • 实际上生成了: class Light extends java.lang.Enum
      • 可以在enum定义体重,添加 字段,方法,构造方法
    3. 注解(annotation) 注记,标记,标注,用于在各种语法要素删加上附加信息,供编译器和其他程序使用
  8. java语言的"指针":引用与指针:

    • 信息:
      1. 引用(reference)实质上就是指针(point)
      2. 引用是受控的,安全的:
        1. 会检查空指针
        2. 没有指针运算 *(p+5)
        3. 不能访问没有引用到的内存
        4. 自动回收垃圾
    • 变通: 数组,指向节点,JNI
    • 判断是否相等:
      • 简单来说: 基本类型:比较值相等 引用类型:引用相等
      • 具体判断:
        • 数值类型:转换后比较
        • 浮点数:最好不直接用 ==, 判断差的绝对值是否很小
        • Double.NAN == Double.NAN 结果是false, 见文档
        • boolean 和int无法比较
        • 枚举类型:可以直接比较,因为内部进行了唯一实例化
        • 引用对象:
          • 直接比较连个引用是否一样
          • 如果要判断内容是否一样,要重写 equals() 方法
          • 如果重写equals方法,最好也重写 hashCode() 方法
        • String 相等:
          • 判断的时候一定不要用 ==,要用equals
          • 但是,字符串常量(string literal)和字符串常量会进行内部化( interned),相同的字符串常量是相等的
  9. java的异常:

    • 分为两种: 运行时异常(及其子类), 受检异常
      • 运行时异常(及其子类)可以不明确处理
      • 受检异常,必须明确进行语法处理,要么捕获 catch,要么抛出 throws
    • 子类如果覆盖了父类的一个方法,子类可以抛出子类异常(更具体的异常),但是不能抛出更一般的异常
    • 自定义异常:
      • 继承自 Exception 或者 某个Exception的子类
      • 异常的链接:
        • 处理异常以后如果需要再次抛出,可以抛出当前异常,可以抛出另一个异常,也可以抛出一个新异常,并把当前异常的cause()作为内部异常一起抛出
  10. 断言和测试:

    1. 断言: assertion
      • 格式: assert 表达式; 或者 assert 表达式:信息;
    2. 测试: JUnit
  11. Java的错误 Error:

    1. 分类: 语法错误(Syntax error), 运行错误(Runtime error), 逻辑错误(Logic error)
  12. 集合,排序:

    1. list和set的区别
      1. List: (Collection的子接口)记录元素的保存顺序, 且允许有重复元素
      2. Set: (Collection的子接口) 不记录元素的保存顺序,且不允许有重复元素
  13. 多线程:

    1. 实现方法:
      1. extends Thread
      2. implements Runnable
      3. 用匿名类, new Thread(){ public void run(){ /* 内容*/ } }
      4. 用lambda表达式, new Thread( ()->{ /* 内容*/ } ).start();
    2. 对线程的控制
      1. 启动: .start()
      2. 结束: . 设定标记变量
      3. 阻止执行
      4. 设定优先级:
    3. 线程类型:
      1. 普通线程(非 deamon线程): 如果一个java程序中还存在deamon线程,程序就不会结束
      2. daemon线程(守护线程,后台线程): 不阻止程序结束
        1. setDaemon(true);
    4. 线程的同步:
      1. 原因: 线程的不确定性: eg: cnt++ 的例子
      2. 概念: 互斥锁:
      3. 用法: synchronized(代码片段) synchronized 方法
        1. 使用 wait() 方法可以释放对象锁
        2. 使用 notify() 或 notifyAll() 可以让等待的一个或所有线程进入就绪状态
      4. 在Java中可以讲wait和notify放在synchronized里面,因为java是这样处理的:
        • 在 synchronized代码执行期间,线程调用对象的wait()方法,会释放对象锁标志,然后进入等待状态,然后由其他线程调用notify()或者notifyAll()方法通知正在等待的线程
      5. 为了避免问题,方便使用,JDK1.5中增加了更多的类,以便更灵活的使用锁机制
        1. java.util.concurrent.locks 包
        2. Lock接口, ReentrantLock 类 : lock() tryLock() unlock()
        3. ReadWriteLock接口, ReentrantReadWriteLock类 .writeLock().lock() .readLock().unlock()
  14. 并发API

    1. 来自: java.util.concurrent包及子包
      • 从JDK1.5开始,提供了一系列的工具,更好更方便地使用线程
      • 实用类: 单变量, 集合, Timer, 线程池
      • 集合与线程:
        • ArrayList/ HashMap是线程不安全的 ----> Vector 和HashTable是线程安全的
        • 产生一个线程安全的集合对象 Collections.synchronizedArrayList(list) // 相对安全一些
      • 方便使用的线程安全类:
        • CopyOnWriteArrayList CopyOnWriteArraySet 适用于很少写入而读取频繁的对象
        • ConcurrentHashMap : putIfAbsent(), remove(), replace()
        • ArrayBlockingQueue: 生产者与消费者, 使用put()及 take()
    2. 原子类型(线程安全) java.util.concurrent.atomic
    3. 线程池:
      1. 相关类: ExecutorService接口, ThreadPoolExecutor 类, Executors工具类
      2. 常见用法: ExecutorService pool = Executors.newCachedThreadPool(); 使用其 execute(Runnable r)方法
    4. Timer 计时器: java.util.Timer 重复某件事, javax.swing.Timer类 重复执行 ActionListener
      1. 特别注意: 在线程中更新图形化界面,要调用 SwingUtilites.invokeLater
  15. 流式操作和并行流: 流式操作 ≈ 流水线操作, 函数式风格的操作

    1. 类似 js的 underscore / lodash
    2. 流操作分成两类:
      1. 中间的: 保持流打开状态,并允许后续操作: filter, sorted, limit, map
      2. 末端的: 必须是对流的最终操作: max, min, count, forEach, findAny
    3. 步骤:获取流,中间操作,末端操作
      1. 数组: Arrays.stream(ary)
      2. Collection(包括List) list.stream()
      3. Map: 没有流,但是有类似方法: map.putIfAbsent map.computeIfPresent map.merge
      4. Stream的子接口: DoubleStream, IntStream, LongStream, Stream
      5. 并行计算: 只需要把 .stream() 换成 .parallelStream() 其他都不变,就可以实现并行计算
  16. 输入输出:

    1. 信息:java.io/ java.nio / java.nio2 文件流,内存流,网络流, 字符流/字符流, 节点流/处理流(过滤流)

      • 输入: 字节流: InputStream 字符流: Reader
      • 输出: 字节流: OutputStream 字符流: Writer
    2. 常用类:

      1. InputStream 类 read()方法, 逐字节地以二进制原始方式读入数据
      2. OutputStream 类 write()方法,
      3. Reader 类
      4. Writer 类
      5. java.util.Scanner 类:(JDK1.5+)
      6. java.nio.file.Files -> readAllLines() 方法
    3. 常见节点流:

    4. 概念:

      1. 流的包装(链接):一个流对象经过其他流的多次包装,称为流的链接。
        • 处理流的构造方法总是要带一个其他的流对象作为参数
        • eg. BufferedReader in2 = new BufferedReader( newInputStreamReader( new FileInputStream(file), "utf-8"));
          • 从字节的 FileInputStream包装成 字符的 InputStreamReader,最后包装成BufferedReader以后,我们就可以执行 in2.readLine();
      2. 获取字符集: Charset.forName("utf8")
    5. 对象的读写: 序列号与反序列化

      1. 使用的类:
        1. 对象: ObjectInputStream, ObjectOutputStream
        2. 基本数据: DataInputStream, DataOutputStream
      2. 必须实现 Serializable 接口,才能实现序列化与反序列化:
        1. 该接口没有方法,只是一个标记
  17. 网络流

    1. 概念
    2. 常用类: URL,
  18. 文件流:

    1. 概念
    2. 常用类: File( 目录也当成File处理), RandomAccessFile
  19. 正则表达式:

    1. 概念: 用于匹配字符串的一种模式 字符{数量}位置
    2. 写法:
    3. 常用类: java.util.regex 模式类 Pattern 匹配类 Matcher, Pattern.matches(pattern, variable)
      • Matcher类的方法:
        • find方法扫描输入序列,寻找下一个与Pattern匹配的地方
        • appendReplacement方法
      • Matcher中的group (分组)
        • group(分组),是指正则表达式中一对圆括号括起来的一部分
        • group(0)或 group()表示整个匹配项, group(1), group(2) 表示各个分组,
        • 替换时, $0 表示整个匹配项,$1, $2 … 表示各个分组(圆括号)
  20. 图形用户界面组件及分类:

    1. 概念:
      • AWT: Abstract Window Toolkit
      • Swing: JDK 1.2以后引入的,功能更强,界面更丰富,轻量级,各种平台上更统一
      • 组件:
        • 容器组件, 非容器组件
        • 容器: 顶层容器(JFrame, JDialog, JApplet ),非顶层容器
        • JComponent: 非顶层容器
      • 实现图形三个步骤: 组件Component,布局 Layout,事件 Event,
    2. 常用类:
      • java.awt 包
        • Frame, Buttom, Label, TextField, TextArea, Panel
      • javax.swing 包
        • JFrame, JButton, Jlabel, Jtextfield, JtextArea, JPanel
    3. 写法:
    4. 事件处理:
    5. 常用组件:
      1. JOptionPane: 约等于 dialog
  21. 网络编程:

    1. 概念:
      1. Socket/ ServerSocket: 客户端和服务端相连的方式
    2. 常用类:
      1. java.net.URL
      2. Appache的 httpclient (外部引用)
    3. 写法:
  22. 多媒体编程:

    1. 概念:
      1. Java Media API
      2. JAI : Java Advanced Imaging
      3. Java 3D
      4. JMF : Java Media Framework
    2. 常用类:
      1. 组件的 get Graphics()
      2. Canvas 及 JComponent 对象 -> Canvas的 paint() JComponent 的 paintComponent(Graphics g)
      3. JPanel -> setDoubleBuffered(true) 画图时间长的情况下,使用双缓存,避免闪烁
      4. Graphics.drawImage() 显示图像
      5. javax.imageio.ImageIO.read( new File() ) 载入图片
      6. BufferedImage 类 后台画图 getGraphics()
      7. ImageIO read() write()
    3. 写法:
  23. 数据库编程:

    1. 概念:
      1. JDBC: Java Database Connectivity. Java8 开始不再支持 ODBC
    2. 常用类:
      1. Connection 连接
      2. Statement 语句
      3. ResultSet 结果集 next() 遍历所有结果
      4. PreparedStatement 经过编译的语句 (多次执行相同语句速度略快, 可以方便地加参数, 避免SQL注入攻击 )
      5. swing.JTable 用于显示的数据表
    3. 写法:
      1. 加载驱动程序 Class.forName("org.sqlite.JDBC");
      2. 得到连接: String connString = "jdbc:sqlite:d:test.db"; Connection conn = DriverManager.getConnection(connString);
      3. 得到 Statement对象 stmt = con.createStatement();
      4. 执行非查询: stmt.executeUpdate("delete from TestTable");
      5. 查询得到数据集: rs = stmt.executeQuery("SELECT * from DemoTable ORDER BY id");
  24. 设计模式:

    1. 分类:
      • Creational Patterns
      • Structural Patterns
      • Behavioral Patterns
    2. GoF 原则:
      1. 单一职责原则
      2. 开放封闭原则
      3. 替换原则
      4. 依赖倒置原则: 高层模块不应该依赖于低层模块,二者都应该依赖于抽象;抽象不一定改依赖于实现细节,实现细节应该依赖于抽象
      5. 接口隔离原则: 客户端不应该依赖它不需要的接口; 一个类对另一个类的依赖应该建立在最小的接口上
    3. GRASP 原则; General Responsibility Assignment Software Pattern
      1. Information Expert (信息专家)
      2. Creator (创造者)
      3. Low Coupling (低耦合)
      4. High Cohesion (高内聚)
      5. Controller (控制器)
      6. Polymorphism (多态)
      7. Pure Fabrication (纯虚构)
      8. Indirection (间接)
      9. Protected Variations (受保护变化)
    4. 常见:
      1. 工厂模式,抽象工厂模式: 隔离内部实现细节
      2. 适配器模式:把一个接口或是类变成另一种,是不兼容的接口兼容
      3. 组合模式 Composite: 一致性地对待组合对象和独立对象,让使用者把单独的对象和组合对象混用
      4. 装饰器模式 Decorator: 为类添加新功能,防止类继承带来的爆炸式增长,为一个对象动态的加上一系列动作,而不需要因为这些动作的不同而产生大量的继承类
      5. 观察者模式 Observer: 隔离事件的发布者和处理者
  25. 反射:

    1. 概念: reflection: 在运行状态中对于任何一个类都能够知道这个类的所有属性和方法,对于任何一个对象,都能够调用它的任何一个方法和属性
      • 在一些框架性的程序中,反射是相当重要的:eg: plugin
      • 跟PHP反射一个样
    2. 常用类:
      • java.lang.reflect.*:
    3. 用法:
      1. 得到Class对象的3种方法:
        1. 类名.class: Class<?> clss = String.class;
        2. 对象.getClass() String str = "abc"; Class<?> cls = str.getClass();
        3. Class.forName(类的全名) Class<?> cls = Class.forName("java.lang.String");
      2. 动态创建对象,调用相关方法
    4. Annotation 注记:添加一些信息,在编译中或者在框架中使用
      1. 自定义注记:
        1. 定义:
          • 使用 @interface 来定义一个类型,表示它是一个注记
          • 使用 方法名() 来表示它的一个属性 (值或数组), 其中 value() 是默认属性,default 表示默认值

以下都是正确的说法

  1. 父类的非私有方法可以被子类自动继承。
  2. 字段变量可以自动赋初值。
  3. 多态是指一个程序中相同的名字表示不同的含义的情况。
  4. 系统在回收垃圾时会自动调用对象的finalize() 方法。
  5. try-with-resources语句可以自动执行close()方法。
  6. Error是Throwable的子类。
  7. Java方法签名包括: 方法头指定修饰符(例如static)、返回值类型、方法名、和形式参数。
  8. Java子类中,使用super访问父类的域和方法 super.attributName = 1; super.parentClassFunction();
  9. java中 final所修饰的变量,是只读量
    • 当使用final修饰变量时,表示该变量是不可改变的
      1. 一个永不改变的编译时常量
      2. 一个在运行时才被赋初值的变量,但不希望该变量的值被修改
  10. 在接口中定义的方法具有public, abstract的特点(Java8以前)
    • 在jdk8之前,interface之中可以定义变量和方法,变量必须是public、static、final的,方法必须是public、abstract的
    • JDK8及以后,允许我们在接口中定义static方法和default方法。
      • 如果两个接口中定义了一模一样的默认方法,并且一个实现类同时实现了这两个接口,那么必须在实现类中重写默认方法,否则编译失败
  11. SimpleDateFormat类可以用来解析日期字符串。 是的, 用parse() 返回Date对象
  12. TreeMap的底层实现是红黑树
  13. Set的主要实现包括HashSet及TreeSet
  14. 迭代的基本模式是while(){ x=f(x); }。
  15. List会记录元素的保存顺序。
  16. List的主要实现包括LinkedList及ArrayList
  17. Queue的主要实现包括LinkedList
  18. for-each语句可以用于所有的Collection及数组。
  19. list和set的区别
    1. List中允许插入重复的元素,而在Set中不允许重复元素存在。 ​
    2. List是有序集合,会保留元素插入时的顺序,Set是无序集合。 ​
    3. List可以通过下标来访问,而Set不能。
  20. Java的集合框架体系总结
    1. Iterator被xxx实现: Collection, ListIterator, Map
    2. Collection 被 Set List 实现
    3. Set 被 HashSet TreeSet 实现
    4. List 被 ArrayList LinkedList 实现
    5. Map 被 HashMap, TreeMap(红黑树)实现
    6. HashSet 被 LinkedHashSet 实现/继承
    7. HashMap 被 LinkedHashMap 实现/继承
    8. Vector HashTable 均已经被替代
    9. java集合继承关系图
  21. 早期类或接口的新版替换:
    1. Vector -> ArrayList 相当于动态数组, 有elementAt
    2. Stack -> LInkedList Stack是Vector的子类,push,pop, peek
    3. Hashtable -> HashMap Hashtable 实现了Map接口,参见Properties类
    4. Enumeration -> Iterator
      • Enumeration用另一种方式实现Iterator功能
  22. JComponent组件都是Container
  23. 事件监听器是一些接口,其中含有一些方法
    • 事件监听器是一些事件的接口, 接口中含有相关的方法, 这些方法带一个事件对象作为参数

以下都是错误的说法:

  1. 如果一个类被abstract所修饰,说明这个类没有构造方法
    • 例子
      • 抽象类的构造方法定义为protected,因为他只能被子类使用,即用super(params);
  2. protected修饰的成员,不能在包中访问,只能在子类中访问。
    • 示意图
  3. private可以修饰类、也可以修饰类的成员(字段、方法)。
    • private只能修饰内部类,不能修饰外部类
    • private关键字只能修饰内部类,不能修饰外部类。 但是,这个地方一定要注意了:内部类中方法只能是static的,因此,内部类也要声明为静态的!
  4. 虚方法调用是指编译时就决定了调用哪个类中的哪个方法。
    • 运行时才知道
  5. instanceof是判断一个对象实例是不是某种类型及其父类型。
    • 只判断一种类型
  6. 抽象类不能有构造方法。
    • 可以有
  7. 匿名类可以定义构造方法。
    • 不可以
  8. 编译器会为所有的类加一个default构造方法,即使用户已定义了构造方法。
    • 用户不写构造方法的时候编译器才会加一个默认的
  9. finally语句是指没有异常出现时要执行的语句。
    • NO
  10. 构造方法(constructor )的返回类型是void。
    • 错误,返回值是构造方法所在类,这个类型的对象
  11. 如果省略访问控制符,则表示private
    • 错误,表示friendly, 包内使用 (待确认)
  12. String 与数组一样,有一个属性叫length。
    • 错误。 string.length() 是方法不是属性。 数组 ( String[] arr ) 才有 .length 属性
  13. String a = "abcdef"; 则a.substring(1,3)的结果为"bcd"。
    • 错误, java的 String.substring 方法的两个参数,是起始和结束位置,不是起始位置和长度
  14. for-each语句可以用于所有的Enumerable对象。
    • 错误 ????
  15. DataOutputStream可以以二进制的方式写入double。
    • 错误 ????
  16. 所有的事件监听接口都可以用Lambda表达式。
    • 错误 针对只有一个方法的接口,可以使用lambda表达式
  17. SQL中语句用双引号表示字符串
    • 错误,用单引号
  18. 方法签名(signature)包括参数的类型及参数的名字。
    • 错误。 包括一堆。。。。
  19. this和super是两个不同的对象
    • 错误。 super是当前对象的父类,不是对象
  20. 如果一个类被abstract所修饰,说明这个类没有构造方法
    • 错误: 抽象类的构造方法定义为protected,因为他只能被子类使用,即用super(paraments);
  21. 实例初始化,先于静态初始化执行
    • 错误: 顺序: 父类静态初始化, 子类静态初始化,父类初始化,父类构造,子类初始化,子类构造
  22. 内部类中不能访问外部类的private字段及方法
    • 错误: 可以的
  23. 若父类中的方法声明了throws异常,则子类Override时一定也要throws异常。
    • 错误: 子类重写父类方法要抛出与父类一致的异常,或者不抛出异常。 子类重写父类方法所抛出的异常不能超过父类的范畴。
  24. Integer I = 5 实际表示Integer I = new Integer(5)。
    • 错误: 1-127 是在integerCache里面的,不会new 一个Integer
  25. 后台线程(deamon)不会自动结束
    • 错误: 守护线程不依赖于终端,但是依赖于系统,与系统“同生共死”。当JVM中所有的线程都是守护线程的时候,JVM就可以退出了;如果还有一个或以上的非守护线程则JVM不会退出
  26. JDBC中RecordSet表示结果集
    • 错误: ResultSet表示结果集, RecordSet目测是VB的
  27. Java中的输入输出流的连接实际上使用了"装饰模式“。
    • 错误:

实例初始化,先于静态初始化执行

各种缩写词

  • POM: Project Object Model
    • Apache Maven,是一个软件(特别是Java软件)项目管理及自动构建工具。基于项目对象模型(缩写:POM)概念,Maven利用一个中央信息片断能管理一个项目的构建、报告和文档等步骤
666    ·   1

(点赞功能开发中)

评论列表
{{item.userName}}
{{item.lastUpdate}}
{{item.content}}
{{item.like}}    |   {{item.unlike}}
{{ sItem.userName }}
{{ sItem.lastUpdate }}
{{ sItem.content }}
{{ sItem.like }}    |   {{ sItem.unlike }}