Java 基础

来源:互联网 发布:mac note 编辑:程序博客网 时间:2024/05/29 11:42

Java 基础累积

1. Java中对象在堆中,引用和原生数据类型在栈中,string对象在堆中和栈(字符串池)中都有。

 

2. 在堆中生成同一类的对象时,无论多少个对象,方法是共享的(没考虑静态属性和方法)。

 

3. 关于String类型,

    1)String str = new String("str"); 若字符串池(位于栈中)没有“str”对象则在堆中和池中都生成“str”对象。

         若字符串池中有“str”对象,则在堆中生成“str”对象。

    2)String str = “str”; 若字符串池没有“str”对象,则在池中生成“str”对象

            若字符串池中有,则str直接指向“str”对象。

 

4. Person person = new Person(); 依次做了三件事

    (1) 为Person对象开辟内存空间;

    (2) 调用构造方法;

    (3) 将对象的地址返回(返回给person引用)。

 

 5. Java继承中

    (1) 生成子类对象的时候,默认调用父类不带参数的构造方法生成父类对象(也可以用super关键字调用指定的父类构造方法,

    但是必须调用父类方法生成父类对象)

    (2) 父类的方法和属性都可以被继承(也可以重写)

    (3) static方法不能被重写(只能被隐藏。)Parent p = new Son(); p.go(); 若go()方法是static的,则执行Parent类的go()方法。

 

6. Java多态

    Class Parent { public void run(){} }
    Class Son extends Parent { public void run(){} }
  

    Parent p = new Son();
    p.run(); 调用子类的run()方法(若Parent类没有run()方法,会发生编译时错误)。  
 

 

7. final关键字

    final修饰的属性,有两种赋值方式。一是定义的时候赋值,二是在所有的构造方法中为它赋值。

 

8. static{}静态代码块(写在类中,不是方法中,也是完成初始化工作),是当该类的.class文件加载到java虚拟机

    的时候执行(这时候还没有创建对象,且只执行一次)。

 

9. 集合

    1)ArrayList

    ArrayList是可变数组(Object[],数组中放的是对象的引用,无法放原生数据类型)初始长度为10

    (可用ArrayList(int a)指定初始长度);

     当长度不够的时候将数组的长度增加到1.5倍+1;

    在ArraList中间插入元素,则需要把后面的元素全部往后移动,所以在ArrayList中插入元素代价很高。

    2)LinkedList

    链表(双向循环链表,每一个对象中,包含了值、上一个对象、下一个对象。

    或则说抽象一点就是本身和上一个的地址和下一个的地址)。

    注:对比ArrayList和LinkedList,ArrayList更适合搜索,LinkedList更适合插入删除。

    3)TreeSet

    TreeSet是排序的Set想在TreeSet中添加对象,通常需要使用TreeSet set = new TreeSet(comparator); 构造方法。

    在implements Comparator类的compare方法中定义比较规则。

    4)Map

    对于HashSet和HashMap都是无序的,set是不能重复(重复无法放入),map是key不能重复(重复了直接覆盖)。

    keySet返回key的集合(Set类型,不可重复),values返回值的集合(Collection类型,可重复)。

    HashSet是使用HashMap实现的,当使用add方法将对象添加到Set当中时,

    实际上是将该对象作为底层所维护的Map对象的key,而value则都是同一个Object对象(该对象我们用不上)

    5)HashMap维护着一个Entry[],HashMap的结构是数组+链表,当put一个值的时候,它会根据put的key的hashCode

    计算出一个位置(准备放Entry对象的位置),如果该位置没有对象存在,就将此对象直接放进数组当中;

    如果该位置已经有对象存在了,则顺着此存在的对象的链开始寻找

   (Entry类有一个Entry类型的next成员变量,指向了该对象的下一个对象),

    如果此链上有对象的话,再去使用equals方法进行比较,如果对此链上的某个对象的equals方法比较为false,

    则将该对象放到数组当中,然后将数组中该位置以前存在的那个对象链接到此对象的后面。

 

10. 数据结构

    一、线性表结构

    1)数组(有索引)

    2)链表(双向循环链表:每一个元素都有该元素的数据、下一个元素、上一个元素)

    3)栈(Stack),后进先出(跌书)

    4)队列(Queue),先进先出(排队上车)

 

11. null

      可以把null强制转化为任意类型,不会报错。

 

12. 泛型(避免类型转化异常)

    当使用如Person<?> 或 Person<? extent Foot>的引用时,只能取得或移除引用指向的对象的属性,不能增加

    (否则就违背了泛型避免类型转化异常的初衷) 

 

13. Integer i = 100;

      Integer i2 = 100;

    i == i2 是true(如果赋值为200则为false),因为Integer会缓存 -128至127之间的数,这些数赋给Integer(不是new)

    则不会生成新的对象。

 

14. 可变参数

    可变参数如: String...(实际上是一个String[]) 一个方法最多只能有一个可变参数,且只能作为最后一个参数。

 

15. 枚举类型enum

    1)枚举和class是一个级别的,每个定义的枚举类都继承Enum。

    2)每个枚举的成员其实就是您定义的枚举类型的一個实例,用“,”隔开。

    3)枚举的成员是固定个数的,在定义枚举的时候就指定,而且都是public static final的。

    4)枚举也有构造方法(只能私有)和属性。

 

16. Class

    一个类的对应的Class对象是该类加载到虚拟机的时候自动生成的,Class类没有公开的Constructor(构造方法)。

 

17. finalize()方法

    JVM在准备释放某个类的内存的时候,会先调用finalize()方法。但是JVM回收内存是不定时的,

    所以通常不要把回收资源的操作卸载finalize()方法中,这样可以避免内存不能及时回收。

 

18. 内部类

    1)静态内部类:只能访问外部类的静态属性或方法(无论是private还是public)。

        生成方式:Outer.Inner iner = new Outer.Inner();

    2)成员内部类:可以访问外部类的所有方法和属性。

    生成方式: Outer.Inner iner = new Outer().new Inner();

    3)局部内部类:方法中的类,访问方法中定义的变量时,该变量必须为final,只能在方法中生成实例(运用较少)。

    4)匿名内部类:通常作为实参传入方法,用于回调。

        如调用go(Date date)方法:

        go(new Date() {}); 此时实参为一个继承了Date的匿名内部类。若“Date”是一个interface,

        则实参为一个实现了 该接口的匿名内部类。

 

19. 多线程

    线程分为4个状态,创建、可运行、运行、消亡(Create、Runable、Running、Destroy)。

    多线程中结束该线程不能使用stop()方法,应该是等待run()方法运行完毕(可用return控制)。

    多线程同步:

    Java中每一个对象都有一个锁(lock)或则叫监视器(monitor))

    1)synchronized成员方法:当一个线程访问一个对象的synchronized成员方法时,会将该对象锁住,

    其他线程无法访问该对象的所有synchronized成员方法,直到方法访问结束。

    2)synchronized静态方法:一个类只有唯一一个Class对象,当一个线程访问该类的synchronized静态方法时,会将

    该类的Class对象锁住,其他线程无法访问该类的所有synchronized静态方法,直到方法访问结束。

    3)synchronized块:synchronized(obj){}

    表示将obj上锁,当obj处于上锁状态的时候,则其他线程无法执行{}中的代码,直到obj(解锁,及执行完毕)。

    通常使用方法3),因为方法3)可以写在方法内部,更加细腻。

   

20. 序列化

    定义:将对象转化为字节流保存起来,并在以后还原这个对象。(Java中的标识性接口,Serializable接口)

    serialVersionUID:

        当对象被序列话到本地文件中的时候,对应的类发生了改变(如增加属性等),在被还原的时候就会出现异常。

    这时候如果加上了serialVersionUID,那么就可以正常还原,多出来的属性会添加缺省值。所以,serialVersionUID

    的作用就是保证类的向后兼容。

    对象序列化:

        当对象被序列化的时候,只会序列化非静态的成员变量(不能保存静态变量和方法),成员变量也可以

    是对象(但是必须也实现了Serializable接口,否则抛出NotSerializableException,当然可以用transient关键字

    标识该对象引用变量,那么序列化的时候就会忽略它)。

    ObjectOutput、ObjectInput接口:

        ObjectOutputStream、ObjectInputStream分别是两个接口实现类,两个类的write方法和read方法可以将对象写、读

    到指定位置。两个类会封装节点流,从而写、读节点流的具体位置。

    当实现了Serializable接口的序列化类中定义了以下两个方法,那么就可以更细致的控制序列化了。

    private void writeObject(java.io.ObjectOutputStream out) throws IOException

    private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException;

 

21. clone(克隆)

    浅克隆:只可能对象中的非引用类型的变量,引用类型变量指向以前的对象。

    深克隆:克隆所有变量。

    浅克隆实现:某个类想要被浅克隆,则需要实现Cloneable接口,并且重写clone方法(并且把修饰符改为public)

    深克隆的实现:利用序列化。

 class Parent implements Serializable {

 private static final long serialVersionUID = -9084900055110218109L;
 
 public String name = "Parent";
 
 public int age = 40;
 
 public Son son = new Son();
 

 /**
  * 利用序列化深克隆
  */
 public Parent copy() {
  
  Parent newParent = null;
  ByteArrayOutputStream bos = new ByteArrayOutputStream();
  
  try {
   ObjectOutputStream oos = new ObjectOutputStream(bos);
   oos.writeObject(this);
   ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bos.toByteArray()));
   newParent = (Parent) ois.readObject();
   
  } catch (IOException e) {
   e.printStackTrace();
  } catch (ClassNotFoundException e) {
   e.printStackTrace();
  }
  
  return newParent;
 }
}

class Son implements Serializable {

 private static final long serialVersionUID = 5736736634035541535L;
 
 public String name = "son";

}

 

   

 

0 0
原创粉丝点击