java原理性总结

  • java为什么不支持多继继承
    围绕钻石形继承问题产生的歧义;多重继承确实使设计复杂化并在转换、构造函数链接等过程中产生问题

  • char 数组比 Java 中的 String 更适合存储密码
    1)由于字符串在 Java 中是不可变的,如果你将密码存储为纯文本,它将在内存中可用,直到垃圾收集器清除它. 并且为了可重用性,会存在 String 在字符串池中, 它很可能会保留在内存中持续很长时间,从而构成安全威胁。
    由于任何有权访问内存转储的人都可以以明文形式找到密码,这是另一个原因,你应该始终使用加密密码而不是纯文本。由于字符串是不可变的,所以不能更改字符串的内容,因为任何更改都会产生新的字符串,而如果你使用char[],你就可以将所有元素设置为空白或零。因此,在字符数组中存储密码可以明显降低窃取密码的安全风险。
    2)Java 本身建议使用 JPasswordField 的 getPassword() 方法,该方法返回一个 char[] 和不推荐使用的getTex() 方法,该方法以明文形式返回密码,由于安全原因。应遵循 Java 团队的建议, 坚持标准而不是反对它。
    3)使用 String 时,总是存在在日志文件或控制台中打印纯文本的风险,但如果使用 Array,则不会打印数组的内容而是打印其内存位置。虽然不是一个真正的原因,但仍然有道理。

  • Serializable类包含一个不可序列化的成员
    任何序列化该类的尝试都会因NotSerializableException而失败,但这可以通过在 Java中 为 static 设置瞬态(trancient)变量来轻松解决。
    1:Java 中的可序列化接口和可外部接口之间的区别是什么
    这是 Java 序列化访谈中最常问的问题。下面是我的版本 Externalizable 给我们提供 writeExternal() 和 readExternal() 方法, 这让我们灵活地控制 Java 序列化机制, 而不是依赖于 Java 的默认序列化。正确实现 Externalizable 接口可以显著提高应用程序的性能。
    2:什么是 serialVersionUID ,如果你不定义这个, 会发生什么
    serialVersionUID 是一个 private static final long 型 ID, 当它被印在对象上时, 它通常是对象的哈希码,你可以使用 serialver 这个 JDK 工具来查看序列化对象的 serialVersionUID。SerialVerionUID 用于对象的版本控制。也可以在类文件中指定 serialVersionUID。不指定 serialVersionUID的后果是,当你添加或修改类中的任何字段时, 则已序列化类将无法恢复, 因为为新类和旧序列化对象生成的 serialVersionUID 将有所不同。Java 序列化过程依赖于正确的序列化对象恢复状态的, ,并在序列化对象序列版本不匹配的情况下引发 java.io.InvalidClassException 无效类异常
    3:序列化时,你希望某些成员不要序列化,你如何实现它
    瞬态和静态变量会不会得到序列化等,所以,如果你不希望任何字段是对象的状态的一部分, 然后声明它静态或瞬态根据你的需要, 这样就不会是在 Java 序列化过程中被包含在内。

  • java的基础类型和字节大小
    java数据类型 字节 表示范围
    byte(字节型) 1 -128~127
    boolean(布尔型) 1 true或false
    short(短整型) 2 -32768~32767
    char(字符型) 2 从字符型对应的整型数来划分,其表示范围是0~65535
    int(整型) 4 -2147483648~2147483647
    float(浮点型) 4 -3.4E38~3.4E38
    double(双精度型) 8 -1.7E308~1.7E308
    long(长整型) 8 -9223372036854775808 ~ 9223372036854775807
    1: 能将 int 强制转换为 byte 类型的变量吗
    我们可以做强制转换,但是 Java 中 int 是 32 位的,而 byte 是 8 位的,所以,如果强制转化,int 类型的高 24 位将会被丢弃,因为byte 类型的范围是从 -128 到 127。
    2: 向上转换:
    整型,字符型,浮点型的数据在混合运算中相互转换,转换时遵循以下原则:
    容量小的类型可自动转换为容量大的数据类型;
    byte,short,char → int → long → float → double
    byte,short,char之间不会相互转换,他们在计算时首先会转换为int类型。
    boolean 类型是不可以转换为其他基本数据类型。

java类初始化顺序

  • 父类静态变量
  • 父类静态代码块
  • 子类静态代码块
  • 父类非静态变量
  • 父类非静态代码块
  • 父类构造函数
  • 子类非静态变量
  • 子类非静态代码块
  • 子类构造函数
    注意:没有则跳过

final, finally, finalize

  • final 用于声明属性,方法和类, 分别表示属性不可变, 方法不可覆盖, 类不可继承.
  • finally 是异常处理语句结构的一部分,表示总是执行.
  • finalize 是Object类的一个方法,在垃圾收集器执行的时候会调用被回收对象的此方法,可以覆盖此方法提供垃圾收集时的其他资源回收,例如关闭文件等. JVM不保证此方法总被调用

ceil floor round

  • ceil该方法就表示向上取整,
  • 所以,Math.ceil(11.3)的结果为12,Math.ceil(-11.3)的结果是-11;
  • floor该方法就表示向下取整,所以,Math.floor(11.6)的结果为11,Math.floor(-11.6)的结果是-12;
  • round方法,它表示“四舍五入”,算法为Math.floor(x+0.5),即将原来的数字加上0.5后再向下取整,所以,Math.round(11.5)的结果为12,Math.round(-11.5)的结果为-11
  • 面向对象的特征

  • 抽象:
    抽象就是忽略一个主题中与当前目标无关的那些方面,以便更充分地注意与当前目标有关的方面。抽象并不打算了解全部问题,而只是选择其中的一部分,暂时不用部分细节。抽象包括两个方面,一是过程抽象,二是数据抽象。
  • 继承:
    继承是一种联结类的层次模型,并且允许和鼓励类的重用,它提供了一种明确表述共性的方法。对象的一个新类可以从现有的类中派生,这个过程称为类继承。新类继承了原始类的特性,新类称为原始类的派生类(子类),而原始类称为新类的基类(父类)。派生类可以从它的基类那里继承方法和实例变量,并且类可以修改或增加新的方法使之更适合特殊的需要。
  • 封装:
    封装是把过程和数据包围起来,对数据的访问只能通过已定义的界面。面向对象计算始于这个基本概念,即现实世界可以被描绘成一系列完全自治、封装的对象,这些对象通过一个受保护的接口访问其他对象。
  • 多态性:
    多态性是指允许不同类的对象对同一消息作出响应。多态性包括参数化多态性和包含多态性。多态性语言具有灵活、抽象、行为共享、代码共享的优势,很好的解决了应用程序函数同名问题。

&和&&

&是位运算符,表示按位与运算,&&是逻辑运算符,表示逻辑与(and)。# 内存管理
JVM会将申请到的内存从逻辑上划分为三个区域:堆、栈、方法区(非堆空间).
堆空间:用于存储对象以及对象的属性成员变量(jVM启动的时候分配的一段可以动态扩容的内存空间)。
栈空间:用于存储程序运行时在方法中中的局部变量和返回值等私有数据。(线程创建的时候分配的固定大小的内存空间
方法区:用于存放常量以及类的元数据。类的元数据包括类的静态变量,类有哪些方法以及这些方法的元数据(名称,参数和返回值等)(jVM启动的时候分配的一段可以动态扩容的内存空间)。
注:堆空间也是垃圾回收器工作的场所,即堆空间中没有可达的引用对象所占用的存储空间会被垃圾回收期回收

  • 局部变量前不能放置任何访问修饰符 。final可以用来修饰局部变量(final如同abstract和strictfp,都是非访问修饰符,strictfp只能修饰class和method而非variable)。
  • abstract的methods不能以private修饰。abstract的methods就是让子类implement(实现)具体细节的. (同理,abstract method前不能加final)。
  • final的instant variable(成员变量)没有default value,必须在constructor (构造器)结束之前被赋予一个明确的值。例如为"final int i = 0;"
  • 任何在interface里声明的interface variable (接口变量,也可称成员变量),默认为public static final。也就是说"Ball ball = new Ball(“PingPang”);“实际上是"public static final Ball ball = new Ball(“PingPang”);”

java中实现多态的机制

靠的是父类或接口定义的引用变量可以指向子类或具体实现类的实例对象,而程序调用的方法在运行期才动态绑定,就是引用变量所指向的具体实例对象的方法,也就是内存里正在运行的那个对象的方法,而不是引用变量的类型中定义的方法。

抽象类和接口

  • 含有abstract修饰符的class即为抽象类,抽象类不能创建的实例对象。含有抽象方法的类必须定义为abstract class.
  • 接口可以说成是一种特殊的抽象类,接口中的所有方法都必须是抽象的。接口中的方法定义默认为public abstract类型,接口中的成员变量类型默认为public static final。
  • 下面比较一下两者的语法区别:
    抽象类可以有构造方法,接口中不能有构造方法。
    抽象类中可以有普通成员变量,接口中没有普通成员变量
    抽象类中可以包含非抽象的普通方法,接口中的所有方法必须都是抽象的,不能有非抽象的普通方法。
    抽象类中的抽象方法的访问类型可以是public,protected和(默认类型,虽然eclipse不报错,但也不行,默认类型子类不能继承),但接口中的抽象方法只能是public类型的,并且默认即为public abstract类型.
    抽象类中可以包含静态方法,接口中不能包含静态方法
    抽象类和接口中都可以包含静态成员变量,抽象类中的静态成员变量的访问类型可以任意,但接口中定义的变量只能是public static final类型,并且默认即为public static final类型。

内部类

  • 内部类之所以能访问外部类,是因为内部类持有了外部类的引用 :外部类.this(静态内部类没有这个,不支持this,直接类名.)
  • 内部类定义局部时,只能访问final修饰的局部变量
  • 内部类是可以继承或者实现外部其他的的类和接口的。好处是:通过内部类的方式对类进行重写或者接口实现,通过公共方式对其内部类对象进行访问,因为通常内部类很有可能被外部类封装其中,我们就可以通过父类或者接口的方式访问到内部类的对象

匿名内部类

  • 抽象方法不能new对象,是因为抽象方法没重写
  • 匿名内部类:就是一个带内容的子类对象。格式:new 父类 or接口{子类的内容}
  • 静态方法访问内部类时,内部类必须是静态的。
  • 若想创建一个类(子类)的对象,并且对象只被创建一个,此时该类不必命名,称 之为匿名内部类
  • 匿名内部类中访问外部的变量,该变量必须是final的.

forward 和redirect的区别

  • forward是服务器请求资源,服务器直接访问目标地址的URL,把那个URL的响应内容读取过来,然后把这些内容再发给浏览器,浏览器根本不知道服务器发送的内容是从哪儿来的,所以它的地址栏中还是原来的地址。
  • redirect就是服务端根据逻辑,发送一个状态码,告诉浏览器重新去请求那个地址,一般来说浏览器会用刚才请求的所有参数重新请求,所以session,request参数都可以获取。

值传递

  • 当一个对象被当作参数传递到一个方法后,此方法可改变这个对象的属性,并可返回变化后的结果,那么这里到底是值传递还是引用传递
  • 是值传递。Java 编程语言只有值传递参数。当一个对象实例作为一个参数被传递到方法中时,参数的值就是对该对象的引用。对象的内容可以在被调用的方法中改变,但对象的引用是永远不会改变的。

垃圾回收的优点和原理

  • Java语言中一个显著的特点就是引入了垃圾回收机制,使c++程序员最头疼的内存管理的问题迎刃而解,它使得Java程序员在编写程序的时候不再需要考虑内存管理。由于有个垃圾回收机制,Java中的对象不再有"作用域"的概念,只有对象的引用才有"作用域"。垃圾回收可以有效的防止内存泄露,有效的使用可以使用的内存。垃圾回收器通常是作为一个单独的低级别的线程运行,不可预知的情况下对内存堆中已经死亡的或者长时间没有使用的对象进行清楚和回收,程序员不能实时的调用垃圾回收器对某个对象或所有对象进行垃圾回收。
  • 回收机制有分代复制垃圾回收和标记垃圾回收,增量垃圾回收。

java对象的强、软、弱和虚四中引用

从JDK 1.2版本开始,把对象的引用分为4种级别,从而使程序能更加灵活地控制对象的生命周期。这4种级别由高到低依次为:强引用、软引用、弱引用和虚引用。

  • 强引用(StrongReference)
    如果一个对象具有强引用,那垃圾回收器不会回收它。当内存空间不足,Java虚拟机抛出OutOfMemoryError错误,使程序异常终止,也不会靠随意回收具有强引用的对象来解决内存不足的问题。

  • 软引用(SoftReference)
    如果一个对象只具有软引用,则内存空间足够,垃圾回收器就不会回收它;如果内存空间不足了,就会回收这些对象的内存。

  • 弱引用(WeakReference)
    弱引用与软引用的区别在于:只具有弱引用的对象拥有更短暂的生命周期。在垃圾回收器线程扫描它所管辖的内存区域的过程中,一旦发现了只具有弱引用的对象,不管当前内存空间足够与否,都会回收它的内存。不过,由于垃圾回收器是一个优先级很低的线程,因此不一定会很快发现那些只具有弱引用的对象

  • 虚引用(PhantomReference)
    虚引用并不会决定对象的生命周期。如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收器回收。
    虚引用主要用来跟踪对象被垃圾回收器回收的活动。
    虚引用与软引用和弱引用的一个区别在于:虚引用必须和引用队列 (ReferenceQueue)联合使用。当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会在回收对象的内存之前,把这个虚引用加入到与之 关联的引用队列中。
    ReferenceQueue queue = new ReferenceQueue ();
    PhantomReference pr = new PhantomReference (object, queue);
    程序可以通过判断引用队列中是否已经加入了虚引用,来了解被引用的对象是否将要被垃圾回收。如果程序发现某个虚引用已经被加入到引用队列,那么就可以在所引用的对象的内存被回收之前采取必要的行动。

细节知识点

  • 数组声明的时候使用 int[] index,而不要使用 int index[] 说明:看起来更符合人的阅读习惯。

  • 将局部变量的作用域最小化:变量的声明应该尽可能靠近变量第一次使用的位置

  • 给if、for、do—while、switch等语句的执行体加大括号{} (即使只有一条语句)

  • 避免随意进行类型强制转换,应改善设计,或在转换前用instanceof进行判断(object instanceof class)

  • 基本类型优于包装类型,注意合理使用包装类型(for循环用的是基本类型,如果定义long,则不停转换)

  • 方法设计应遵循单一抽象层次原则(SLAP)
    说明:SLAP原则,是指让一个方法中所有的操作处于相同的抽象层。否则跳跃的代码的抽象层次破坏了代码的流畅性

  • 当父类和子类有同名静态方法时,声明父类变量引用子类实例,调用该静态方法时调用的是父类的静态方法,而非子类的静态方法

  • 日志工具对象logger应声明为private static final

  • 使用System.arraycopy()进行数组复制

  • 在Java的IO操作中,尽量使用带缓冲的实现 .对于性能要求更高的实现,可以使用Java NIO

  • 字符串大小写转换时,应加上Locale.US, (例如:testString.toUpperCase(Local.US));

  • 非信任代码:非产品包中的代码,如通过网络下载到本地虚拟机中加载并执行的代码。

  • POJO 类中布尔类型的变量,都不要加 is,否则部分框架解析会引起序列化错误。

  • 包名统一使用小写,点分隔符之间有且仅有一个自然语义的英语单词。包名统一使用 单数形式,但是类名如果有复数含义,类名可以使用复数形式。

  • 不允许任何魔法值(即未经定义的常量)直接出现在代码中。

  • Object 的 equals 方法容易抛空指针异常,应使用常量或确定有值的对象来调用 equals。
    正例:“test”.equals(object);
    反例:object.equals(“test”);

  • 关于基本数据类型与包装数据类型的使用标准如下:
    1) 所有的 POJO 类属性必须使用包装数据类型。
    2) RPC 方法的返回值和参数必须使用包装数据类型。
    3)所有的局部变量使用基本数据类型。

  • 在包装类的内存中有一块区域,缓存着Integer的byte范围内的值(-128~127),如果未超出此范围,则直接在该缓存区取值,并不会在堆中创建新对象,如果超出此范围则会在堆内存中创建新对象.
    如果i=128超出了取值范围,双等号比较为false,内容相同equals比较为true
    注意:如果i=127,通过new关键字创建的对象也是两个对象,通过valueOf()创建的对象为同一个对象.

集合处理

  • 关于 hashCode 和 equals 的处理,遵循如下规则:
    1) 只要重写 equals,就必须重写 hashCode。
    2) 因为 Set 存储的是不重复的对象,依据 hashCode 和 equals 进行判断,所以 Set 存储的 对象必须重写这两个方法。
    3) 如果自定义对象做为 Map 的键,那么必须重写 hashCode 和 equals。 说明:String 重写了 hashCode 和 equals 方法,所以我们可以非常愉快地使用 String 对象 作为 key 来使用。
  • 使用集合转数组的方法,必须使用集合的 toArray(T[] array),传入的是类型完全 一样的数组,大小就是 list.size()。
  • 使用 entrySet 遍历 Map 类集合 KV,而不是 keySet 方式进行遍历。 说明:keySet 其实是遍历了 2 次,一次是转为 Iterator 对象,另一次是从 hashMap 中取出 key 所对应的 value。而 entrySet 只是遍历了一次就把 key 和 value 都放到了 entry 中,效 率更高。如果是 JDK8,使用 Map.foreach 方法。
   HashMap hm=new HashMap();
        hm.put("name", "zhangsan");
        hm.put("age", "18");
       Set< Map.Entry<String,String>> entrySet = hm.entrySet();
       Iterator< Map.Entry<String,String>> iter=entrySet.iterator();
       while(iter.hasNext())
       {
      Map.Entry<String,String> entry=iter.next();
           System.out.println(entry.getKey()+"\t"+entry.getValue());
       }        

并发处理

  • 线程池不允许使用 Executors 去创建,而是通过 ThreadPoolExecutor 的方式,这样 的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。
  • FixedThreadPool 和 SingleThreadPool: 允许的请求队列长度为 Integer.MAX_VALUE,可能会堆积大量的请求,从而导致 OOM。
  • CachedThreadPool 和 ScheduledThreadPool: 允许的创建线程数量为 Integer.MAX_VALUE,可能会创建大量的线程,从而导致 OOM。
  • SimpleDateFormat 是线程不安全的类,一般不要定义为 static 变量,如果定义为 static,必须加锁,或者使用 DateUtils 工具类。
  • 正例:注意线程安全,使用 DateUtils。亦推荐如下处理:
private static final ThreadLocal<DateFormat> df = new ThreadLocal<DateFormat>()
{      
   @Override  
  protected DateFormat initialValue()    
 {  
         
  return new SimpleDateFormat("yyyy-MM-dd");      
 }   
};   

说明:如果是 JDK8 的应用,可以使用 Instant 代替 Date,LocalDateTime 代替 Calendar, DateTimeFormatter 代替 SimpleDateFormat,官方给出的解释:simple beautiful strong immutable thread-safe。

  • 高并发时,同步调用应该去考量锁的性能损耗。能用无锁数据结构,就不要用锁;能 锁区块,就不要锁整个方法体;能用对象锁,就不要用类锁。
  • 对多个资源、数据库表、对象同时加锁时,需要保持一致的加锁顺序,否则可能会造 成死锁。
  • 使用 CountDownLatch 进行异步转同步操作,每个线程退出前必须调用 countDown 方法,线程执行代码注意 catch 异常,确保 countDown 方法被执行到,避免主线程无法执行 至 await 方法,直到超时才返回结果。 说明:注意,子线程抛出异常堆栈,不能在主线程 try-catch 到。
  • ThreadLocal 无法解决共享对象的更新问题,ThreadLocal 对象建议使用 static 修饰。这个变量是针对一个线程内所有操作共享的,所以设置为静态变量,所有此类实例共享 此静态变量 ,也就是说在类第一次被使用时装载,只分配一块存储空间,所有此类的对象(只 要是这个线程内定义的)都可以操控这个变量。

常用加密算法

对称加密:DES、3DES、AES等

  • 优缺点
    优点:算法公开、计算量小、加密速度快、加密效率高。
    缺点:在数据传送前,发送方和接收方必须商定好秘钥,然后使双方都能保存好秘钥。其次如果一方的秘钥被泄露,那么加密信息也就不安全了。另外,每对用户每次使用对称加密算法时,都需要使用其他人不知道的唯一秘钥,这会使得收、发双方所拥有的钥匙数量巨大,密钥管理成为双方的负担。
  • 应用
    保存用户手机号、身份证等敏感但能解密的信息

非对称加密:RSA、DSA、ECC等

  • 优缺点
    非对称加密与对称加密相比,其安全性更好:对称加密的通信双方使用相同的秘钥,如果一方的秘钥遭泄露,那么整个通信就会被破解。而非对称加密使用一对秘钥,一个用来加密,一个用来解密,而且公钥是公开的,秘钥是自己保存的,不需要像对称加密那样在通信之前要先同步秘钥。
    非对称加密的缺点是加密和解密花费时间长、速度慢,只适合对少量数据进行加密。

  • 应用
    一般用于签名和认证

散列算法:MD5、SHA、HMAC等
在信息安全技术中,经常需要验证消息的完整性,散列(Hash)函数提供了这一服务,它对不同长度的输入消息,产生固定长度的输出。这个固定长度的输出称为原输入消息的“散列”或“消息摘要”(Message digest)。

  • 应用
    效验下载文件正确性,一般在网站上下载文件都能见到
    存储用户敏感信息,如密码、 卡号等不可解密的信息
    很多博客把Base64编码也当做一种加密算法来解释,这是不严谨的。Base64是没有可读性,但不代表这个编码就是加密的。加密需要保证没有密钥的人无法解密信息,更无法从密文中破解任何明文信息,但Base64可以很轻松的反编码。另外,Base64编码也显然没有用到密钥,不具有加密算法的安全性。
  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值