天天看点

某次笔试问题总结(全选择题)

考得很细。

1、String问题

//注:字符串常量池从jdk1.7之后已经从方法区,转移到了堆中
        String s = new String("123") ;
        //一共创建2个对象,在String Pool中创建1个字符串对象指向"123"这个字符串字面量(作为String类的构造函数参数)
        //因为是"new"所以自然要在堆中创建1个字符串对象,地址指向s

        String s1 = "123";
        String s2 = new String("123");
        //这时的new创建只创建1个字符串对象,因为在s1 = "123"这一步已经在String Pool中创建了1个123对象
        //这时new String(“123”)的构造函数参数"123"则直接用已经放在String Pool的字符串对象,在堆中创建1个对象

        //考虑下面的问题
        String str1 = new String("ABC");
        String str2 = new String("ABC");
        System.out.println(str1 == str2);//False.
        String str3 = "ABC";
        String str4 = "ABC";
        String str5 = "A" + "BC";
        System.out.println(str3 == str4); //True.
        System.out.println(str3 == str5); //True.
        String a = "ABC";
        String b="AB";
        String c=b+"C";
        System.out.println(a==c); //false

        //字符串常量池(String Pool)保存着所有字符串字面量(literal strings),这些字面量在编译时期就确定。
        //不仅如此,还可以使用 String 的 intern() 方法在运行过程将字符串添加到 String Pool 中.
        //当一个字符串调用 intern() 方法时,如果 String Pool 中已经存在一个字符串和该字符串值相等(使用 equals() 方法进行确定),那么就会返回 String Pool 中字符串的引用;
        //否则,就会在 String Pool 中添加一个新的字符串,并返回这个新字符串的引用。
        String s3 = new String("aaa");
        String s4 = new String("aaa");
        System.out.println(s3 == s4);           // false
        String s5 = s1.intern();
        String s6 = s1.intern();
        System.out.println(s5 == s6);           // true
        //练习题(不考虑字符串在常量池中已存在的情况)
        String a0="123";//创建1个对象
        String a1=new String("123");//2个对象
        String a2="123"+"456";//2个
        String a3="123"+new String("456"); //4个对象
           
拼接效率:StringBuilder > StringBuffer > str + “ ”,StringBuilder线程不安全,StringBuffer线程安全
           

2、Math类方法

//指数函数方法
        System.out.println(Math.exp(8));
        System.out.println(Math.log(8));
        System.out.println(Math.log10(8));
        System.out.println(Math.sqrt(8));

        //取整函数方法,本次笔试考了这个
        System.out.println(Math.ceil(5.2));//6.0
        System.out.println(Math.floor(5.2));//5.0
        System.out.println(Math.rint(5.2));//5.0
        System.out.println(Math.rint(5.6));//6.0rint,个人总结:四舍六入五靠偶
        System.out.println(Math.rint(4.5));//4.0,偶数
        System.out.println(Math.rint(-4.5));//-4.0偶数
        System.out.println(Math.round(5.5f));//6,返回int,参数上加0.5然后进行下取整
        System.out.println(Math.round(5.5));//6,long,参数上加0.5然后进行下取整
        System.out.println(Math.round(-5.5));//-5
        System.out.println(Math.round(-5.6));//-6

        //最值、绝对值函数
        System.out.println(Math.max(4,8));
        System.out.println(Math.min(4,8));
        System.out.println(Math.abs(-5.2));

        //Math.random()随机数方法
        System.out.println(Math.random());//double,0<=double<1
        System.out.println(4+(int)(Math.random()*100));//4<=返回<104
        System.out.println(new Random().nextInt(104));

        //三角函数
        System.out.println(Math.sin(Math.PI/2));//1.0
        System.out.println(Math.acos(Math.sqrt(2)/2));//0.7853981633974483,即π/4
           

3、if()括号内赋值问题

boolean flag = false;
        if (flag = true){//Test
            System.out.println("Test");
        }else{
            System.out.println("Test2");
        }
        System.out.println(flag);//true

        if (flag = false){//Test4
            System.out.println("Test3");
        }else {
            System.out.println("Test4");
        }
        System.out.println(flag);//false
        //注意:括号内赋值只能是boolean变量
        int a;
        if(a = 4){//Error: java: 不兼容的类型: int无法转换为boolean
            System.out.println("");
        }
           

4、补码与位运算符

//在计算机系统中,数值一律用补码来表示(存储)。计算机一般采用整型数据为32位二进制数
        //主要原因:使用补码,可以将符号位和其它位统一处理;
        //同时,减法也可按加法来处理。另外,两个用补码表示的数相加时,如果最高位(符号位)有进位,则进位被舍弃。
        int i = 0XFFFFFFF1;
        System.out.println(i);//-15
        System.out.println(~i);//输出为14,~i是对-15的补码0XFFFFFFF1取反
                                //则得到补码1110,因为符号位变成了0,所以是得到的补码是正数
                                //正数的补码反码都是其本身,所以1110变为十进制显示就是14
           

这里顺便复习一下平常很少用的位运算符:

  1. “按位与”运算:&
  2. ”按位或“运算:|
  3. ”按位取反“运算:~
  4. ”按位异或“运算:^
  5. ”移位操作“:<<左移(空位补0),>>右移(最高位0空位补0,最高位1空位补1),>>>无符号右移(空位补0)

5、构造函数与静态代码块等执行顺序

执行顺序:(优先级从高到低)静态代码块>mian方法>构造代码块>构造方法

其中静态代码块只执行一次。构造代码块在每次创建对象是都会执行。

  1. 普通代码块:在方法或语句中出现的{}就称为普通代码块。普通代码块和一般的语句执行顺序由他们在代码中出现的次序决定–“先出现先执行”

    构造代码块

  2. 构造代码块:直接在类中定义且没有static修饰没有名字的{}代码块称为构造代码块。

    构造代码块在每次创建对象时都会被调用,并且构造代码块的执行次序优先于类构造函数。

  3. 静态代码块:static修饰

如果结合了继承的问题,则顺序为父类静态代码块———子类静态代码块——父类构造代码块——父类构造方法——子类构造代码块——子类构造方法。

需要注意的是,在实例化子类对象时,父类无参构造方法将被自动调用,但有参构造方法并不能被自动调用,只能依赖于super关键字显式地调用父类的构造方法。更需要注意的是,平时我们新建一个类,会自动提供一个无参的构造方法,但如果一个类已经存在一个有参构造方法,则系统不会再隐式为我们提供无参构造方法。

6、内部类问题

内部类可分为成员内部类、局部内部类、匿名内部类。

6.1、成员内部类

  1. 内部类可以直接使用外部类中的成员方法和成员变量
  2. 内部类实例一定要绑定在外部类实例上,如果从外部类中初始化一个内部类对象,则完成了绑定。
  3. 初始化方式和其他相同,都是用new关键字
  4. 成员内部类不能存在任何static变量和方法
  5. 依赖于外部类对象,没有外部类对象就没有内部类对象
  6. 内部类可以向上转型为接口

    private class InnerClass implements OutInterface{}

  7. this获取内部类和外部类的引用
public class TheSameName{
	private int x;
	private class Inner{
		private int x = 9;
		public void doIt(int x){
			x++;//形参x
			this.x++;//内部类变量x
			TheSameName.this.x++;//外部类变量x
			}
		}
	}
           

6.2、局部内部类

在类的局部位置定义,如在类的方法或任意的作用域中。

  1. 被定义在方法内部后,不能在方法外部访问该内部类
  2. 可以访问当前代码块的常量和此外部类的所有成员
  3. 方法参数设置为final类型

6.3、匿名内部类

  1. 实质:创建的是继承了类或实现了接口的子类匿名对象
  2. 前提条件:必须继承一个父类或实现一个接口
  3. 没有名称,所以使用默认构造方法类生产对象,记住匿名类定义结束后要加分号;
  4. 编译后产生以“外部类$序号”为名称的.class文件,序号以1~n排列,分别代表n个匿名内部类。
  5. 最常用的情况就是在多线程的实现上,因为要实现多线程必须继承Thread类或是继承Runnable接口

6.4、静态内部类

在内部类前添加static,就变成静态内部类了。

  1. 静态类对象创建不需要外部类对象
  2. 静态内部类不能访问外部类的非静态的变量和方法
public class OuterClass {

    class InnerClass {
    }

    static class StaticInnerClass {
    }

    public static void main(String[] args) {
        // InnerClass innerClass = new InnerClass(); // 'OuterClass.this' cannot be referenced from a static context
        OuterClass outerClass = new OuterClass();
        InnerClass innerClass = outerClass.new InnerClass();
        StaticInnerClass staticInnerClass = new StaticInnerClass();
    }
}
           

7、static变量及方法访问方式

在Java中,访问static变量和方法有两种方式:

1 通过一个对象去访问,就像访问非静态变量和方法一样

2 通过类去访问,这是常用方式

public class StaticTest {
    private static String a;
    private static void doStatic(){
        System.out.println("静态方法");
    }
    public static void main(String[] args) {
        System.out.println(StaticTest.a);

        StaticTest.doStatic();//方式1

        StaticTest staticTest = new StaticTest();
        staticTest.doStatic();//方式2

        StaticTest staticTest1;
        staticTest.doStatic();//方式3
    }
}

           

结果:

某次笔试问题总结(全选择题)

我们都知道方式1的使用是正确的,但考试会经常考方式2方式3,问你能不能编译成功,然后如果编译成功会不会抛出异常。

8、Java内存回收

我还没有系统学习JVM虚拟机,所以对这方面的知识了解很少。但笔试又经常考这个的选择题,又苦于现在没时间。于是决定每天学一点,抽出睡前和吃饭时间看书学习。

某次笔试问题总结(全选择题)

现在转载一下这个博主写的文章。

Java垃圾回收–强引用、软引用、弱引用、虚引用 详细

当程序员通过new关键字创建对象,即视为为Java对象申请内存空间。JVM会在堆内存中为每个对象分配空间;当一个对象失去引用的时候,JVM垃圾回收机制会自动清除他们,并回收他们所占用的内存空间。

Java内存管理包括内存分配(创建Java对象的时候)和内存回收(回收 Java对象的时候)两个方面。

JVM垃圾回收机制是否回收一个对象的标准:是否有引用变量引用该对象?

9、计算机网络相关

9.1、电子邮件协议

常用的电子邮件协议有SMTP、POP3、IMAP4,它们都隶属于TCP/IP协议簇,默认状态下,分别通过TCP端口25、110和143建立连接。

SMTP的全称是“Simple Mail Transfer Protocol”,即简单邮件传输协议。它是一组用于从源地址到目的地址传输邮件的规范,通过它来控制邮件的中转方式。SMTP 协议属于TCP/IP协议簇,它帮助每台计算机在发送或中转信件时找到下一个目的地。SMTP 服务器就是遵循SMTP协议的发送邮件服务器。SMTP认证,简单地说就是要求必须在提供了账户名和密码之后才可以登录 SMTP 服务器,这就使得那些垃圾邮件的散播者无可乘之机。增加 SMTP 认证的目的是为了使用户避免受到垃圾邮件的侵扰。 SMTP已是事实上的E-Mail传输的标准。

10、Map相同键名问题

Map map = new HashMap();
        map.put("name",null);
        map.put("name","123");
        System.out.println(map.size());

        Map map1 = new HashMap();
        map1.put("name","123");
        map1.put("name","456");
        System.out.println(map1.size());

        map.putAll(map1);
        System.out.println(map.size());

        System.out.println(map.get("name1"));
           
某次笔试问题总结(全选择题)

结论:

  1. put相同键名的键值对,则新增的值会覆盖原来的值
  2. get不存在的键,不会报错,会返回null

11、线程同步方式

通过Object的wait和notify

通过Condition的awiat和signal

通过一个阻塞队列

通过两个阻塞队列

通过SynchronousQueue

通过线程池的Callback回调

通过同步辅助类CountDownLatch

通过同步辅助类CyclicBarrier

实现线程同步的几种方式总结

12、设计模式

Refactoring:clean your code

笔试考到了桥接模式和单例模式

jdbc规范使用到主要涉及的设计模式:桥接模式

单例模式(Singleton Pattern)是 Java

中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。

这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。

  1. 单例类只能有一个实例。
  2. 单例类必须自己创建自己的唯一实例。
  3. 单例类必须给所有其他对象提供这一实例。
某次笔试问题总结(全选择题)

我们将创建一个 SingleObject 类。SingleObject 类有它的私有构造函数和本身的一个静态实例。

SingleObject 类提供了一个静态方法,供外界获取它的静态实例。SingletonPatternDemo,我们的演示类使用

SingleObject 类来获取 SingleObject 对象。

单例模式的6种实现方式

//1、懒汉式,线程不安全
public class Singleton {  
    private static Singleton instance;  
    private Singleton (){}  
  
    public static Singleton getInstance() {  
    if (instance == null) {  
        instance = new Singleton();  
    }  
    return instance;  
    }  
}
//2、懒汉式,线程安全
public class Singleton {  
    private static Singleton instance;  
    private Singleton (){}  
    public static synchronized Singleton getInstance() {  
    if (instance == null) {  
        instance = new Singleton();  
    }  
    return instance;  
    }  
}
//3、饿汉式(一般情况下建议使用)
public class Singleton {  
    private static Singleton instance = new Singleton();  
    private Singleton (){}  
    public static Singleton getInstance() {  
    return instance;  
    }  
}
//4、双检锁/双重校验锁(DCL,即 double-checked locking)
public class Singleton {  
    private volatile static Singleton singleton;  
    private Singleton (){}  
    public static Singleton getSingleton() {  
    if (singleton == null) {  
        synchronized (Singleton.class) {  
        if (singleton == null) {  
            singleton = new Singleton();  
        }  
        }  
    }  
    return singleton;  
    }  
}
//5、登记式/静态内部类
public class Singleton {  
    private static class SingletonHolder {  
    private static final Singleton INSTANCE = new Singleton();  
    }  
    private Singleton (){}  
    public static final Singleton getInstance() {  
    return SingletonHolder.INSTANCE;  
    }  
}
//枚举
public enum Singleton {  
    INSTANCE;  
    public void whateverMethod() {  
    }  
}
           
一般情况下,不建议使用第 1 种和第 2 种懒汉方式,建议使用第 3 种饿汉方式。只有在要明确实现 lazy loading 效果时,才会使用第 5 种登记方式。如果涉及到反序列化创建对象时,可以尝试使用第 6 种枚举方式。如果有其他特殊的需求,可以考虑使用第 4 种双检锁方式。

13、I/O流

13.1、

13.2、

13.3、

14、Socket编程