java的一些要点

2018-06-03  本文已影响0人  pluss

Java常量池

静态常量池,即class文件中的常量池,class文件中的常量池不仅仅包含字符串字面量,符号引用,还包含类、方法的信息,占用class文件绝大部分空间。
运行时常量池,则是jvm虚拟机在完成了装载操作后,将class文件中的常量池载入到内存中,并保存在方法区中,我们常说的常量池,就是指方法区中的运行时常量池。

String s1 = new String("a");
创建了两个对象。
1、在class被ClassLoader加载时,"a"被作为常量读入,放进了常量池。
2、new String()是从常量池复制来的新的String对象,被放进堆中。
对象引用s1指向堆中的"a"。

String s1="123";
String s2="1"+"23";//编译时常量拼接,优化为"123"
final String s3="1";
String s4=s3+"23";//因为s3是常量,所以可以优化为"123"
//s1==s2 --> true
//s1==s4 --> true

intern() 会得到字符串对象在常量池中引用,如果常量池中没有对应的字符串,则该字符串将被添加到常量池中,然后返回常量池中的引用。

System.out.println(new String("a")=="a");//false
System.out.println(new String("a").intern()=="a");//true

JAVA语法糖“+”运算符

因为用+进行字符串连接会创建多个String对象,所以jdk1.5开始,带有字符串变量的连接操作,jvm内部采用的是StringBuilder来实现的,而之前这个操作是采用StringBuffer实现的。

Integer a = null;
String b = a+"123"; 
//b--> "null123"

装箱:new StringBuilder().append(a).append("123").toString();
StringBuilder的append(Object obj)方法调用了String.valueOf(Object obj),将null转变为字符串。

public static String valueOf(Object obj){
    return (obj==null)?"null":obj.toString();
}

3+""//String.valueOf(3)+""
i==i+1;//i.intValue() == i.intValue()+1
i==1;//i.intValue() == 1

虚拟机规范没有限制什么时候进行类加载但对初始化有严格的规定。
初始化触发条件如下
Java中类的初始化
1. new时、读取或设置一个类变量(常量除外)时、调用类的静态方法时。即遇到new、getstatic、putstatic、invokestatic这四条字节码指令时如果类还没初始化,则需要先触发其初始化。
2. 使用java.lang.reflect包的方法反射调用类时。
3. 当初始化一个类时如果发现其父类还没进行初始化,则需要先触发其父类的初始化。(接口除外)
4. main方法所在的类会自动被jvm初始化。

以上对类的主动引用会触发初始化,其他所有引用类的方式不会触发初始化,称为被动引用。
1. 通过子类引用父类中的静态字段,子类不会被初始化,但父类
2. 数组定义不会初始化该类。它的字节码指令是newarray,是对数组引用类型的初始化,数组引用类型由虚拟机自动生成。
3. 常量在编译阶段会存入调用它的类的常量池中,本质没有直接引用到定义该常量的类,因此不会触发定义常量的类的初始化。

    public void run(int i, char x){System.out.println("int,char");}
    public void run(char x,int i){System.out.println("char,int");}

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

public class IOTest {

    /**
     * 字符流的写入
     * @param file
     * @param content
     */
    public void writeFileByWriter(File file, String content) {
        
        FileWriter o = null;
        try {
            o = new FileWriter(file);// FileWriter继承了OutputStreamWriter
            o.write(content);
            o.flush();// 将缓冲区数据写入目标文件中
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (o != null) {
                try {
                    o.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    }
    /**
     * 字符流的读取文件
     * @param file
     */
    public void readFileByReader(File file) {
        FileReader fr = null;
        try {
            fr = new FileReader(file);
            // int ch = 0;
            // while ((ch = fr.read()) != -1) {// read()返回一个字符
            // System.out.println((char) ch);
            // }
            char[] buf = new char[1024];
            int len = 0;
            while ((len = fr.read(buf)) != -1) {// 读一串进char数组中,返回读的数量
                System.out.println(new String(buf, 0, len));
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (fr != null) {
                try {
                    fr.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    /**
     * 
     * @param source
     * @param target
     */
    public void copyFileByCharBuffer(File source, File target) {
        BufferedReader bi = null;
        BufferedWriter bo = null;
        try {
            bi = new BufferedReader(new FileReader(source));
            bo = new BufferedWriter(new FileWriter(target));
            String line = null;// readLine()读取行,只返回换行符之前的数据
            while ((line = bi.readLine()) != null) {
                bo.write(line);
                bo.newLine();// 换行
            }
            bo.flush();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {// 关闭缓冲区时,缓冲区会顺带关闭它的流。
            if (bi != null) {
                try {
                    bi.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (bo != null) {
                try {
                    bo.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    /**
     * 字节流的写入
     * @param file
     * @param content
     */
    public void writeFileByStream(File file, String content) {
        FileOutputStream o = null;
        try {
            o = new FileOutputStream(file);
            byte[] buf = content.getBytes();
            o.write(buf);// write(buf)字节数组
//          o.flush();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (o != null) {
                try {
                    o.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    /**
     * 字节流的读取文件
     * @param file
     */
    public void readFileByStream(File file) {
        FileInputStream i = null;
        try {
            i = new FileInputStream(file);
//          int ch = 0;
//          while ((ch = i.read()) != -1) {// read()返回一个字节byte
//              System.out.println((char) ch);
//          }
            byte[] buf = new byte[1024];
            int len = 0;
            while ((len = i.read(buf)) != -1) {// 读一串进byte数组中,返回读的数量
                System.out.println(new String(buf, 0, len));
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (i != null) {
                try {
                    i.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    /**
     * 
     * @param source
     * @param target
     */
    public void copyFileByStreamBuffer(File source, File target) {
        BufferedInputStream bi = null;
        BufferedOutputStream bo = null;
        try {
            bi = new BufferedInputStream(new FileInputStream(source));
            bo = new BufferedOutputStream(new FileOutputStream(target));
            int len = 0;
            byte[] buf = new byte[1024];
            while ((len = bi.read(buf)) != -1) {
                bo.write(buf,0,len);
            }
            bo.flush();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {// 关闭缓冲区时,缓冲区会顺带关闭它的流。
            if (bi != null) {
                try {
                    bi.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (bo != null) {
                try {
                    bo.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }


}


Java初级面试题

  1. 面向对象4个特征:
  1. Math.round(x) => Math.floor(x+0.5),即将原来的数字加上0.5后再向下取整
  2. 一个".java"源文件中可以有多个类,但只能有一个public的类,并且public的类名必须与文件名相一致。
  3. 访问权限修饰符protected 允许子类访问
  4. interface 变量默认为public static final 类型,方法默认为public abstract类型
  5. native 本地。表示该方法要用另外一种依赖平台的编程语言实现。
  6. synchronized 使用的同步锁对象是this。抽象方法无法确定this是什么。
  7. 内部类不能定义静态成员,可以访问外部类中的成员变量(静态内部类不可以)。方法内定义的内部类类似局部变量不能有访问修饰符,但可以有final和abstract
  8. final修饰方法,子类不能覆盖该方法但可以继承?继承逻辑是什么?创建子类对象是会先调用父类构造方法
  9. String是final类型,不可继承修改,被设计成不可变类,所有对象都是不可变对象。提高效率用StringBuffer
  10. StringBuffer没有覆盖equals方法和hashcode方法,所以将其存进集合类(hashmap等)中会出现问题
  11. 字符串常量缓冲区,new String(“123”)字符串常量缓冲区看有无“123”,没有创建“123”对象,有直接从缓冲区拿“123”,用来创建新的String对象
  12. 编译优化:String a = "1"+"2"+"3";==>String a = "123";
  13. finally和return谁先?try的return表达式执行后再执行finally,如果finally有return最后返回的是finally的
上一篇 下一篇

猜你喜欢

热点阅读