JAVA科目二

安全

  • 不安全的算法: AES-ECB,DES, MD5
  • 安全加密算法:RSA,DSA/ECDSA和加入盐值SHA256 , AES-GCM
    • 选择AES时需要注意是否切换为GCM模式,默认的ECB模式不安全
    • RSA算法需要将证书长度设置为超过2048才算安全算法
  • 输入校验不能检验CSRF攻击
  • 不要使用XMLDecoder进行反序列化操作
  • 一个对象存入Hash集合后hashcode随即发生变化会导致内存泄漏
  • 敏感数据传输先前面再加密
  • 数值运算,建议使用先决条件检查、Math.*Exact()方法、向上类型转换等方式防止溢出
  • 文件路径校验前必须先进行标准化处理,建议使用getCanonicalPath()
  • ZipInputStream中解压文件必须进行安全检查
      1. 解压出的标准化路径文件在解压目标目录之外
      1. 解压的文件消耗过多的系统资源
  • 不要依赖平台默认的字符编码方式,使用UTF-8
  • 字符串大小写转换(String类的toUpperCase()和toLowerCase()方法、format()方法)必须加上Locale.ROOT或Locale.ENGLISH
  • 个人数据:自然人的email地址、电话号码、生物特征(指纹)、位置数据、IP地址、医疗信息、宗教信仰、社保号、婚姻状态、银行卡、口令、身份证、护照号等。
  • 敏感个人数据:工会成员信息、个人信仰观念(政治、信仰、党派、宗教、性取向)、个人种族信息、犯罪处分负向记录、权威社会识别标识(政府等权威机构发布的能够唯一识别到用户的标识符,一般终身不可重置)、身份认证凭据、生物特征、健康信息、金融帐号标识;
  • SQL注入
    • 使用参数化查询:最有效的防护手段,对于sql语句中的表名、字段名、部分场景下的in条件不适用;
    • 对不可信数据进行白名单校验:适用于拼接sql语句中的表名、字段名
    • 对不可信数据进行转码:仅适用于SQL语句中由单引号或双引号限制的字段
  • XML
    • xml实体解析导致的安全风险:XXE, 内部实体扩展
    • 针对XML数据应用的攻击:XPath,XXE, 内部实体扩展
    • 防止XML注入不包括使用XML Schema或 DTD校验
  • DOS攻击
    • 敏感异常:
      • Java.lang.OutOfMemoryError
      • Java.lang.StackOverflowError
      • javax.naming.InsufficientResourcesException
  • 数据校验
    • 不可信数据进行校验时,禁止使用assert
    • "白名单"方式净化的方式包括删除,编码 ,替换

IO

  • Runtime.exec()方法与相关联的ProcessBuilder.start()方法可以用来调用外部程序进程,这些外部程序运行时Process对象会产生哪些流
    • 输入流,输出流,错误流
  • 规则6.2 禁止将Buffer对象封装的数据暴露给不可信代码
  • 规则6.3 防止让外部进程阻塞在输入输出流上
  • 规则6.4 对于从流中读取一个字符或字节的方法,使用int类型的返回值
  • FileChannel 是写操作 线程安全的
  • File:
    • 仅创建一个File类实例,Java是不会对文件进行读写的
    • File实例可以判断是否目录或文件,因此文件与文件夹都可以处理
  • 字符和字节流
    • Reader 是字符缓存流,可以支持按字符,数组,行来读取。
    • InputSteam是字节缓存流,支持按字节读取文件和二进制数据。

Java 基础

  • 优先加载静态方法块,再加载父类代码块和构造方法,再加载子类。

  • ?: 三元云算符 会返回一个综合类,例如 condition? int: char 会返回一个int

  • 如何遍历删除数组元素避免ConcurrentModificationException

    • 使用removeIf方法或者Iterator提供的remove方法,用于删除当前元素
    • 使用并发集合类来避免ConcurrentModificationException,比如使用CopyOnArrayList,ConcurrentHashMap或者CopyOnWriteArrayList。而不是ArrayList。
    • 如果直接使用stream.list.foreach 或者 foreach 中删除则会引发ConcurrentModificationException
    • ArrayList只能删除倒数第二个元素。
    • LinkedList只能删除倒数第二和第一个元素。
    • 否则抛出ConcurrentModicationException
  • switch

    • switch不支持boolean,long,float
    • switch中,default都是最后匹配的,如果被匹配到没有break,就会继续往下走。直到执行完或break;
  • Java文件执行顺序选择

    • 加载 -> 校验 -> 使用代码
    • 父静态代码块> 子静态代码块> 父代属性初始化> 父代码块> 父构造函数> 子代属性初始化> 子代码块> 子构造函数
  • interface的默认修饰符是 public static final

  • try catch final

    • 不管有没有出现异常,finally块中代码都会执行;
    • 当try和catch中有return时,finally仍然会执行;
    • finally是在return后面的表达式运算后执行的(此时并没有返回运算后的值,而是先把要返回的值保存起来,不管finally中的代码怎么样,返回的值都不会改变,任然是之前保存的值),所以函数返回值是在finally执行前确定的;
    • finally中最好不要包含return,否则程序会提前退出,返回值不是try或catch中保存的返回值。
    • 在final中执行代码发生异常时,直接忽略或仅记录日志,否则会导致finally代码块无法正常结束。进而导致try catch中的异常的抛出,也会影响返回值。
  • Optional 类:

    • 禁止对Optional对象赋值/返回为null,或与null比较;
    • 不应该返回 Optional<'Integer> 、 Optional<'Long> 、 Optional<'Double> ,而应该使用
      OptionalInt 、 OptionalLong 、 OptionalDouble
  • java使用DatagramPacket来打包数据,使用DatagramSocket来发送和接收数据.

  • Path中没有exists、isExists方法,Files中没有isExists方法

  • fetchSize控制了JDBC每次读取数据的行数,越大性能越高,太大可能会内存溢出(OOM)

NIO Selector

  • 一个Selector对应多个Channel,一个选择器最多可以同时被63个通道
  • 注册监听事件:Connect,Accept,Read,Write
  • Java普通IO是面向流的,NIO是面向缓冲区的
  • Selector等事件就绪后才会返回,避免IO阻塞,NIO各种流是非阻塞的,如果没有数据可用也不会阻塞线程
  • Selector是Channel的复用器,不用Close

Buffer

  • flip()方法将Buffer从写模式切换到读模式,将position值重置为0,limit的值设置为之前的position值
  • BufferedReader是字符缓存流,能够更有效地读取字符、数组和行,提供按行读取的功能。
  • BufferedInputStream是字节缓存流,能够按字节读取文件流,不仅能够读取文本文件,还能读取二进制数据,无按行读取的功能
  • wrap()、slice()、duplicate()这些方法会创建一个新的buffer对象,但是修改这个新的buffer对象会导致原始的封装数据也被修改,反之亦然。

多线程

  • Synchronized
    • 使用Synchronized锁某个对象时,只有地址相同才会互斥:
      • 例:
      • public String a = “123”
        synchronized(a) {…}
        a对象引用的是常量池中的“123”的String的地址,如果在别的线程中也锁住了该地址,则会造成竞争
      • public String a = new String(“123”)
        a对象引用的是新声明的字符串的地址,不会与其他线程造成竞争。
    • synchronized修饰非静态方法时,锁住的是当前实例;
    • synchronized修饰静态方法时,锁住的是该类的Class对象;
    • synchronized修饰静态代码块时,锁住的是synchronized关键字后面括号内的对象。
    • synchronized的代码块具有原子性。
    • 在异常条件下,同步方法或者块同步中使用的对象内置锁会自动释放。

  • violated
    • volatile无法实现原子性,只能实现可见性
    • 使用volatile在效率上比较低。
    • 当且仅当满足以下所有条件时,才应该使用volatile变量:
      •   * 对变量的写入操作不依赖变量的当前值,或者你能确保只有单个线程更新变量的值。
          * 该变量没有包含在具有其他变量的不变式中,防止影响其他变量??
          * 防止代码重排
        
  • Sleep是Thread的方法,不会释放锁。
  • Wait是Object的方法,会释放锁,通过notify或notifyAll唤醒。wait必须在synchronize中
  • Join的底层也是调用了Wait,所以也会释放锁。
  • yield不会释放锁,而是会释放CPU给更高优先级的线程
  • 实现多线程
    • 扩展类Thread
    • 实现Runnable接口
    • 实现Callable接口
      • 与Runnable的区别:Callable的任务执行后可返回值,call方法可以抛出异常,运行Callable任务可以拿到一个Future对象,表示异步计算的结果。
  • 线程安全
    • Java多线程程序中,线程不允许抛出未捕获的Checked Exception
    • Java多线程程序中,建议使用Thread对象的setUncaughtExceptionHandler方法注册Runtime异常的处理者
  • Semaphore
    • 定义n个处理器,线程调用acquire尝试获取处理器权限,否则阻塞。完成后调用release释放。Semaphore(int n, boolean isFair),第二个入参定义是否是按顺序获取权限。如果信号量(处理器)为负数(-n),则代表有n个进程正在等待进入临界区。(临界区为Semaphore保护起来的区域)
    • 每wait一次 semaphore都会-1,每signal一次都会让semaphore+1。假设semaphore初始值为2,经过操作后变为-2,则代表现在有2个线程已在临界区,还有2个在临界区外。
  • CountDownLatch
    • 定义一个数字,每countDown便-1,为0时释放权限;为0时,无法重置。
  • Interrupt
    • 如果线程阻塞时,将抛出InterruptException
    • 不推荐使用stop()
    • 调用interrup()后不会直接中断线程,而是给目标线程中断信号,目标线程中断标记置为true
    • 正常的退出方式是在run中检查isInterrupted,然后抛出异常来退出(或者return);
    • 线程本身用Thread.interrupted() 方法检查自己是否被中止。
    • 注意,不可以使用 Thread.current().isInterrupted() 检查自己是否被interrupt,因为isInterrupted() 不会
      清除一个线程的interrupted status。

类加载器

  • 加载器种类
    • 根类加载器(bootstrap class loader):加载$JAVA_HOME中jre/lib/rt.jar里所有的class,不继承自 java.lang.ClassLoader
    • 扩展类加载器(extensions class loader):加载$JAVA_HOME中jre/lib/ext.jar里所有的class
    • 系统类加载器(app class loader):加载当前应用classpath下的所有jar包和类
  • 加载机制
    • 全盘负责:当一个类加载器负责加载某个Class时,该Class所依赖和引用其他Class也将由该类加载器负责载入
    • 当存在继承时,先加载父类和子类的静态代码块,再加载父类的代码块和构造方法,最后再加载子类的代码块和方法

GC

  • gc主要回收堆区和方法区,栈区调用完会自动释放
    • 会被回收的有:
      • private static A a = new A();
      • public void main(){
          A innera = new A()
        }
    • 不会被回收的有:
      • private / public String str = “123”
      • “123”
  • GC root对象包括:虚拟机栈中的对象,方法区中类静态属性引用的对象和常量引用的对象,Native方法引用的对象。
  • 可以在循环之外的节点主动GC
  • 禁止使用主动GC(除非在密码,RMI等方面),尤其是在频繁/周期性的逻辑中
  • 进行IO操作时,应该在try-with-resource或者finally里关闭资源
  • 将对象作为key存入hashMap后,禁止对该对象的任意属性进行赋值操作
  • JVM GC性能指标吞吐量是指 CPU运行用户代码的时间与CPU总消耗时间的比值
    • 吞吐量 = 运行用户代码时间 / (运行用户代码时间 + 垃圾回收时间)
  • 可能触发GC的条件:MaxDirectMemeorySize写满、 永生代(Perm)或Metaspace被写满、年老代(tenured)被写满、显示调用System.gc
  • 想要确定是哪些类的实例占内存较多,可以使用 jmap -histo (pid) 命令
  • 主动调用GC,不能保证马上回收,也不能保证一定会回收
  • java进程频繁GC,用 jstat 定位

数据类型

  • Integer在-128到127之间存在缓存,可以使用==比较
  • byte类型大小范围为-128到127
  • Switch不支持的类型包括boolean,long
  • map属于中间结果
  • long,会根据虚拟机的位数变化长度,int永远是32位
  • double+ int 会被转形为double
  • int + string 会被转换成string
  • 基础类型转换的排序:byte1 char2 -> int3 -> long 8-> float4 -> double8

反射

  • Class类
    • getField/ getFields:返回一个 Feild对象或Field对象的数组,它反映当前 Class对象所表示的类或接口的指定名称的 公共成员字段。
    • getDeclaredField/getDeclaredFields :返回一个包含某些Field 对象的数组,该Field对象反映当前Class 对象所表示的类或接口中 指定名称的 并且在该类中声明的字段
    • getMethod方法则根据方法名称和相关参数,来定位需要查找的Method对象并返回。
    • getDeclareMethods方法的区别在于,返回一个Method对象数组,需要自己在结果中查找所需Method对象。

集合(Collections)

  • TreeMap 可以有null 的key不能有null的value
  • HashMap 可以有null 的key和value,不保证顺序
  • linkedHashMap会将最近一次访问的放在最后一位
  • Set不允许重复元素,无序
  • 线程安全:
    • 线程安全的集合:Vector,HashTable,StringBuffer,ConcurrentHashMap,Stack
    • 非线程安全的集合:ArrayList,LinkedList,HashMap,HashSet,TreeMap,TreeSet,StringBulider,LinkedHashSet,LinkedHashMap
  • 长度:ArrayList(默认10)、Vector(默认10)、StringBuilder(默认16)、StringBuffer(默认16)、HashMap(默认16)、HashSet(默认16)

栈帧

  • 储存方法局部变量,操作堆栈,动态链接,方法返回地址
  • 大小在程序编译时确定
  • 堆外内存: -XMS -XSS -XX:DirectMemorySize
    • -Xms、-Xmx分配用来设置进程堆内存的最小大小和最大大小
    • -Xmn用来设置堆内新生代的大小,老生代的大小= -Xmx减去-Xmn
    • -Xss设置每个线程可使用的内存大小
    • XX:DirectMemorySize用来设置堆外内存

JVM

  • 默认jvm参数运行时不会拆箱和装箱
  • Jmap:分析堆内存,对象数量,分析内存逃逸
    • jmap可以查看堆中对象的统计信息,包括类名,对象数量和内存大小
    • 可以获取每个class的对象数目,占用内存大小和类全名信息
    • jmap可以把堆中的对象dump到本地文件
    • jmap可以打印堆中的配置情况和使用清,还有使用的gc算法 (jmap -heap pid)
    • ​ jmap -histo<java_pid> 打印当前对象的个数和大小
  • Jstack:分析死锁,死循环,线程快照, 等待IO,Object.wait() 问题
  • Jconsole:分析死锁,性能调优工具
  • Jstat:监控资源和性能:展示类加载,内存,垃圾回收状态。
  • Jcmd:执行GC,查看进程信息
  • Jinfo:可以查看或调整系统参数

异常

  • 运行时异常:
    • RuntimeException
    • ArrayStoreException
    • ClassCastException
    • IllegalArgumentException
    • IndexOutOfBoundsException
    • NoSuchElementException
    • NullPointerException
  • 非运行时异常
    • IOException
    • SQLException
    • 用户自定义异常

泛型

  • 泛型容器之间没有继承关系
    • 虽然Apple和Fruit有继承关系,但是Plate和Plate是没有继承关系的。想要Plate的引用传递给Plate,就需要用到泛型通配符。
static class Fruit {}
static class Apple extends Fruit{}
static class Plate<T>{
   public Plate(T t){}
}
Plate<Fruit> p = new Plate<Apple>(new Apple()); // 此处会编译报错
  • 通配符 ? 与 T 的区别:https://segmentfault.com/a/1190000020497160

  • 泛型通配符:?

    • <? extends T>不能使用add方法,适合频繁往外读取内容的
    • <? super T>不能使用get方法,适合经常往里插入的

Clone

  • 需要实现Clonable接口,clonable接口中的clone方法默认是浅拷贝(引用传递):新的对象,但是对象中的数组指向相同的地址。

排版

  • 避免文件过长,不超过2000行
  • 一行代码量最多120
  • 避免方法过长,不超过50行(非空非注释)
  • 嵌套不超过4层,入参不超过5个
  • 一个源文件按顺序包含版权、package、import、顶层类,且用空行分隔
  • import包应当按照先安卓,华为公司,其它商业组织,其它开源第三方、net/org开源组织、最后java的分类顺序出现,并用一个空行分组

Stream

  • 无存储,Stream不是一种数据结构,也不保存数据,数据源可以是数组、容器、I/O或Channel等;
  • 为函数式编程而生,对Stream的任何修改都不会修改数据源;
  • 惰性执行,Stream上的中间操作并不会立即执行,只有等到用户真正需要结果时才会执行;
  • 一次消费,Stream只能被消费一次,一旦遍历过就会失效,就像容器的迭代器那样,想要再次遍历必须重新生成
  • 中间操作:
    • filter
    • map /flatMap
    • distinct
    • sorted
    • peek
    • limit
    • skip
  • 终端操作
    • forEach / forEachOrder
    • toArray
    • reduce
    • collect
    • min / max / count
    • allMatch / anyMatch / noneMatch
    • findFirst / findAny

ORM框架

  • $和#,哪个可以防止SQL注入
    • $在预编译阶段会替换变量,会存在SQL注入问题
    • #{}传入的参数,ORM会默认将其当做字符串处理
  • ORM依赖于JDBC和DataSource
  • ORM有多种实现,主流的Mybatis与Hibernate
  • ORM、对象关系转换,即数据库的单条数据与Java对应之间的映射

序列化

  • 实现Serializable接口的可序列化类建议不使用默认的serialVersionUID
  • Xstream 比 XMLDecoder 更安全,可以使用白名单。
  • 禁止序列化非静态的内部类
  • 序列化只能保存对象的非静态成员交量,不能保存任何的成员方法和静态的成员变量
  • 一个子类实现了Serializable接口,它的父类都没有实现Serializable接口,要想将父类对象也序列化,就需要让父类也实现Serializable接口
  • 序列化对象中的HashMap、HashSet或HashTable等集合不能包含对象自身的引用
  • 建议除非必须使用的第三方接口要求必须实现Serializable接口,否则请选用其它方式代替
  • 实现Serializable接口的可序列化类不要使用默认的serialVersionUID

继承、重载、覆盖

  • 子类继承父类时,只能覆盖同名的方法,不能覆盖同名的变量

  • 子类必须调用父类的构造方法,否则编译失败、

  • 重载(一个类中):是指一个类中定义了多个同名的方法,它们的参数列表是不相同的(参数的个数、参数类型、参数顺序)

    • 子类不能重载父类的private方法,如果子类中也定义了同名方法。只是重新定义了一个新的方法
    • 重载具有相同的(名字)和不同的(签名)

  • 覆盖

    • 子类中覆盖方法必须和父类中被覆盖的方法中函数名和参数和返回值和所抛出的异常都相同;
    • 子类不能覆盖父类的私有(private)方法,因为子类不能继承父类的私有方法,所以子类不是覆盖,而是定义了一个新的方法。
    • 子类不能覆盖父类的静态(static)方法,但是可以重写并屏蔽父类的静态方法(不适用Override)
    • 子类不能覆盖父类的final(final)方法。

  • 隐藏

    • 一个属性静态方法或内部类可以分别隐藏(hide)在其父类中可访问到的具有相同名字(对方法而言就是相同的方法签名)的所有属性、方法或内部类。 上述成员被隐藏后,将阻止其被继承。
  • 遮掩

    • 而遮掩却是变量遮掩类型和包声明,类型声明遮掩包声明。
  • 遮蔽

    • 遮蔽是相同元素之间的遮蔽,变量遮蔽变量,类型声明遮蔽类型声明,函数遮蔽函数。
  • 例题:

    public class Father {
        public int age = 50;

        public void speak() {
            System.out.println("I'm Father");
        }
    }

    public class Son extends Father{
        public int age =25;

        public void speak() {
            System.out.println("I'm Son");
        }
    }
    Father father = new Father();
    Father son = new Son();

    father.speak();
    son.speak();
    System.out.println(father.age);
    System.out.println(son.age);
输出:I'm Father
	  I'm Son
	  50
	  50

黑盒测试

  • 划分等价类的六大原则:
    • 在输入条件规定了取值范围或值的个数的情况下,则可以确立一个有效等价类和两个无效等价类。
      • 例:手机号码
    • 在输入条件规定了输入值的集合或者规定了“必须如何”的条件的情况下,可确立一个有效等价类和一个无效等价类。
    • 在输入条件是一个布尔量的情况下,可确定一个有效等价类和一个无效等价类. 布尔量是一个二值枚举类型, 一个布尔量具有两种状态: true 和 false 。
    • 在规定了输入数据的一组值(假定n个),并且程序要对每一个输入值分别处理的情况下,可确立n个有效等价类和一个无效等价类。
    • 在规定了输入数据必须遵守的规则的情况下,可确立一个有效等价类(符合规则)和若干个无效等价类(从不同角度违反规则)。
    • 在确知已划分的等价类中各元素在程序处理中的方式不同的情况下,则应再将该等价类进一步的划分为更小的等价类。

组合测试

  • 因子组合:
    • AC (All Combinations)所有组合 :组合个数=所有因子的取值个数乘积
    • EC( Each Choice )出现一次就行:组合个数=最多取值的因子的取值个数
    • BC(Basic Choice)以一个为基础 每次改变一个:组合个数=所有因子的取值-因子个数+1
    • N-wise:每N个测试因子的取值组合至少覆盖一次
    • EC 是最少的的数据组合覆盖测试方式。

Linux chmod权限

  • 三位数分别代表拥有者(u) 、群组(g) 、其它组(o)。其中4,2,1分别代表读,写,执行。 4+2+1 =7 即代表拥有所有权限:例如 chmod 777;

正则

  • \d,\w和\s,w 是 word 的简写,表示匹配一个常用字符,包括字母、数字、下划线。s 是 space 的简写,表示匹配一个空格.
  • 将字母换成大写,就表示相反的意思。用 \d 你可以匹配一个数字,\D 则表示匹配一个非数字.
  • . 符号匹配任意字符一次
  • * 符号匹配字符任意次
  • + 符号匹配字符1次
  • ?符号匹配字符1或0次
  • [] 取反的方式是:[^],比如不能是 [123] 的表示方法为 [^123] 或者 [^1-3]
  • ^在[]外表示以什么开头
  • $表示以什么结尾
  • 7
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值