2021-08-10

牛客刷题总结--Java

2021-8-10

  1. 以下代码是否有报错?
    	Object obj = new Object() {
    		public boolean equals(Object obj) {
    			return true;
    		}
    	};
    
    这段代码是没有报错的,这其实是创建了一个匿名内部类,然后重写了父类的 equals() 方法。
  2. String s = new String("xyz") 创建了几个String Object?
    一个或两个都有可能
    String类型是非常特殊的Java类型,它可以被字面量赋值,也可以被对象赋值。在下面这段代码中
    int i = 1 是字面量赋值,其对应的对象赋值是这样的:Integer I = new Integer(1)
    字面量存储在JVM的常量池中,对象存储在堆中,是两个完全不同的概念。
    new String("xyz") 的过程中,会先去常量池中检索是否有"xyz",如果没有,会先在常量池中创建"xyz"然后再在堆中创建该对象。
  3.  	Integer i = 42;
     	Long l = 42l;
     	System.out.println(i.equals(l));
    
    上面这段代码,输出为何?
    flase
  4. System.arraycopy()、clone()、Arrays.copyOf()、for()循环,这四个方法用来拷贝List的效率如何?
    从左到右,效率依次递减
    第一个是Native方法且在JVM中预写好,速度最快
    第二个是Native方法但未预写,速度其次
    第三个本质是调用第一个方法
    第四个非Native最慢

2021-8-16

  1. 用户线程与守护线程(Daemon)
    在Java中线程分为用户线程和守护线程,它们的实质其实是一样的,都继承自Thread类,但不同之处在于守护线程服务于用户线程,一旦JVM中所有的用户线程全部结束,即使守护线程没有结束仍在运行,JVM也会退出。即,用户进程全部结束后,不管守护线程的死活,程序都会直接退出。
    守护线程的定义是在调用start()方法之前,我们通过setDaemon(true)将调用这个方法的线程定义为守护线程。如果这个方法没有在start()执行前调用,则会抛出IllegalThreadStateException,但程序不会中断,我们想设为守护线程的那个线程将被作为用户线程start。从这里也可以看出用户线程和守护线程的实质其实是相同的。
    除了new()方法外,我们还可以通过以下方式调用构造器:
    • 在类的内部通过this.构造方法 调用
    • 在子类可以通过super.父类构造方法 调用
    • 众所周知的反射
  2. 内存泄漏最直接的表现是?
    def:JVM中对象引用消失,GC无法回收该对象所占用的内存,内存像是油罐车的油罐罐身上破洞了一样,不再能储满油气,此为内存泄漏。
    内存泄漏最直接的表现就是抛出内存控制相关的异常,比如OutOfMemoryException
  3. 以下代码的显示结果为?
    public class Demo {
    	    class Super {	
    		    int flag = 1;		
    		    Super() {
    		      test();
    		    }
    		    void test() {
    		      System.out.println("Super.test() flag=" + flag);
    		    }
    		}
    		
    		class Sub extends Super {
    			 Sub(int i) {
    			      flag = i;
    			      System.out.println("Sub.Sub()flag=" + flag);
    			 }
    			 void test() {
    			      System.out.println("Sub.test()flag=" + flag);
    			 }
    		}
    		
    		public static void main(String[] args) {
    			 new Demo().new Sub(5);
    	    }
    }	
    
    即使在父类构造器中调用被重写的方法,也是调用的被重写方法。
    代码执行顺序:
    • 父类静态对象,父类静态代码块
    • 子类静态对象,子类静态代码块
    • 父类非静态对象,父类非静态代码块
    • 父类构造函数
    • 子类非静态对象,子类非静态代码块
    • 子类构造函数
  4. 下面代码返回值为什么?
    package test; 
    import java.util.Date; 
    public class SuperTest extends Date{ 
    	private static final long serialVersionUID = 1L;
    	private void test(){ 
    		System.out.println(super.getClass().getName()); 
    	}
    	public static void main(String[]args){ 
    		new SuperTest().test(); 
    	}
    }
    
    getClass()方法返回的是运行时类的Class,它被final修饰不可被子类重写,想要获取父类的Class应该使用getSuperClass()方法。
  5. 下列Java代码中a、b、c分别在内存的什么区域存储?
    class A {
        private String a = “aa”;
        public boolean methodB() {
            String b = “bb”;
            final String c = “cc”;
        }
    }
    
    堆、栈、栈
    堆区: 只存放类对象,线程共享;
    方法区: 又叫静态存储区,存放class文件和静态数据,线程共享;
    栈区: 存放方法局部变量,基本类型变量区、执行环境上下文、操作指令区,线程不共享;
  6. 假设a是一个线程1和线程2共享的全局变量,则线程1和线程2同时执行下面代码,最终a的结果可能为?
    0,-1,-2
    这里主要考虑a在读写时发生并发。

2021.9.2

  1. 区分运算符与表达式
    ++、+=等为运算符,它们不会让变量的类型改变,而表达式的最低运算类型为int,低于int类型的变量都会被转为int类型然后再计算,举个例子
    char c1 = 'a';
    System.out.println(c1+1);
    System.out.println(++c1);
    
    这段代码的输出为:
    98
    b
    
    再看一段代码
    char c2 = 'a';
    c2++;
    c2 = c2 + c2;
    
    这段代码第三行会报错而第二行不会,因为++是运算符,并不会改变 c2 的数据类型,而 c2 = c2 + c2 是表达式赋值,表达式计算两个 c2 的结果为int类型,把它不经转换的强行赋值给char类型自然就报错了。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值