java面试-基础(一)

1.原始类型和引用类型
- 引用实例变量的缺省值为 null,而原始类型实例变量的缺省值与它们的类型有关,除了boolean的初始值是false以外,其他的都是0的一种表现方式(比如0,0.0f,0.0d)
- @Deprecated(since="9")
public Integer(int value) {
this.value = value;
}

推荐使用工厂模式Integer.valueOf()
- Intenger.MIN_VALUE没有对应的int正整数(因为补码)
- 对于基本类型的封装类的自动装箱,不要在循环中使用
- 对原始类型的赋值,会开辟新的内存,修改一个不会对另一个造成影响「1」
- 对象都是引用类型,创建时在堆内存中
- 多个变量被赋予同一个对象时,他们指向的是同一内存「2」

一段测试代码:(不要介意尾注释,这里只是为了方便)

import java.util.ArrayList;
import java.util.List;

/**
 * <p>pakage: PACKAGE_NAME,descirption:</p>
 *
 * @author wanghai
 * @version V1.0
 * @since <pre>2018/6/18 下午10:39</pre>
 */
public class j {
    public static void main(String[] args) {
        Integer a = 120; // Integer a = Integer.valueOf(120);
        int b = 120;
        int k = b;
        Integer c = 120;
        Integer d = new Integer(120);
        Integer e = Integer.valueOf(120);
        System.out.println(a == b);   // true
        System.out.println(a == c);   // true
        System.out.println(a == d);   // false
        System.out.println(b == d);   // true
        System.out.println(k == d);   // true
        System.out.println(a == e);   // true
        System.out.println(b == e);   // true
        System.out.println(b == k);   // true
        // 修改基本类型的值,另一个值不改变
        b = 100;
        System.out.println(b + "--" + k);

        Integer g = 128;
        Integer f = 128;
        Integer n = g; // 引用,指向同一地址
        int h = 128;
        Integer l = -128;
        Integer m = -128;
        System.out.println(g == f); // false 超出-128~127
        System.out.println(g == n); // true  引用,指向同一地址
        System.out.println(f == h); // true  自动拆箱,依然true
        System.out.println(l == m); // true
        // 修改引用对象的值,导致另一个指向同一地址的对象的值也改变
        n = 10000;
        System.out.println(g + "--" + n); // TODO:128--10000(按道理不是应该都变化?)

        // ------------------------------------------
        List<Integer> numbers1 = new ArrayList<>(10);
        numbers1.add(10);
        // numbers1------size: 1第一个数:10
        System.out.println("numbers1------size: " + numbers1.size() + "第一个数:" + numbers1.get(0));
        List numbers2 = numbers1;
        numbers2.add(99);
        // numbers2------size: 2第一个数:10
        System.out.println("numbers2------size: " + numbers2.size() + "第一个数:" + numbers2.get(0));
        // numbers1------size: 2第二个数:99
        System.out.println("numbers1------size: " + numbers1.size() + "第二个数:" + numbers1.get(1));
    }
}
  • 在-128和127之间,jdk对-128~127之间的值做了缓存,对于-128~127之间的值会取缓存中的引用,所以除非显式调用new操作,该区间的值,Integer与Integer调用==方法返回true;
  • 无论如何,对于相同的值,int与Integer调用==方法,返回true。因为Integer调用了intValue()方法进行了自动拆箱操作
  • TODO:代码中System.out.println(g + "--" + n); // TODO:128--10000(按道理不是应该都变化?)
  • 原始类型不能使用泛型类型定义,也就是不能使用List< int>
  • 只要使用引用,就应该注意null问题。所以自动拆箱时,也是又可能发生空指针异常的。

2.静态方法和静态变量,为了避免混淆,便于区分,最好只通过类名来调用

3.Object类被继承时可以被重写的方法
非final的public、protected方法可以被重写,比如:
hashCode(),toString(),equals(),finalize(),clone(),wait(),notify()/notifyAll(),wait()
注意:

  • HashCode()返回的是int,所以,对于某一对象,其实例最多有2 32 32 次方个不同的hash值。
  • HashCode()和equals()应该:“捆绑重写“
  • 如果某一对象的所有实例(假设保存在HashMap中)都返回同一hash值,那么该HashMap的性能就相当于链表的性能了。
    TODO: hashCode(),equals()重写的深度实践

4.不可变对象是线程安全的,比如像String这样的对象,其一旦实例化,值永远不会变化。所有的数值的封装类,比如Integer、Double这些,都是线程安全的,但是int、long这些原始类型,不是线程安全的。可以参考这个例子以及stackoverflow的讨论

5.什么是驻留
String常量池(享元模式的应用)中的字面量,当被多次引用时,叫做驻留。
不仅是String字面量(一对引号之间的所有字符),任何实例化的String实例都可以使用inter()方法来将其添加到常量池之中去。
这些常量被放置于’Metaspace’中——一个JVM中占用内存的一等公民,不会被垃圾回收机制所回收(PermGen空间在Java8中被完全废除,取而代之的是metaspace直接使用本地内存),PermSize和MaxPermSize JVM参数将被忽略,OOM也会相对的减少一些。
部分参考自此文

@Test
    public void intEquality(){
        final Integer int1 = Integer.valueOf(new String("99"));
        final Integer int2 = Integer.valueOf("99");
        //assertTrue(int1 == int2);
        Assert.assertSame(int1,int2);
    }

6.类型协变体(covariance)
B是A的子类,但是List< B>不是List< A>的子类

7.描述异常层次结构中的核心类
这里写图片描述
图片引用自falkhausen,(未申请转载图片,侵删)

  • 所有的可以被抛出的类都是Throwable的子类。
  • Error: 程序无法处理的错误,表示运行应用程序中较严重问题。大多数错误与代码编写者执行的操作无关,而表示代码运行时 JVM(Java 虚拟机)出现的问题。
  • Exception:又分为运行时异常——(RuntimeException, unchecked exception,非检查异常)和检查异常(checked exception,编译异常)。
  • 运行时异常,即RuntimeException:在运行时才能被发现,java编译器不要求必须进行异常捕获处理或者抛出声明,由程序员自行决定。 比如常见的NullPointerException、ArrayIndexOutOfBoundsException。
  • 检查异常: java编译器强制程序员必须进行捕获处理,比如常见的IOExeption和SQLException。对于非运行时异常如果不进行捕获或者抛出声明处理,编译都不会通过。
  • An Error is a subclass of Throwable that indicates serious problems that a reasonable application should not try to catch. (我们不不应该捕捉error)

8.原生函数
使用native关键字说明这个方法是原生函数,也就是这个方法是用C/C++语言实现的,并且被编译成了DLL,由java去调用。这些函数的实现体在DLL中,JDK的源代码中并不包含

参考

[1] metaspace
[2] [原始类型的线程安全问题]
[3] 异常层次结构

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在信号处理领域,DOA(Direction of Arrival)估计是一项关键技术,主要用于确定多个信号源到达接收阵列的方向。本文将详细探讨三种ESPRIT(Estimation of Signal Parameters via Rotational Invariance Techniques)算法在DOA估计中的实现,以及它们在MATLAB环境中的具体应用。 ESPRIT算法是由Paul Kailath等人于1986年提出的,其核心思想是利用阵列数据的旋转不变性来估计信号源的角度。这种算法相比传统的 MUSIC(Multiple Signal Classification)算法具有较低的计算复杂度,且无需进行特征值分解,因此在实际应用中颇具优势。 1. 普通ESPRIT算法 普通ESPRIT算法分为两个主要步骤:构造等效旋转不变系统和估计角度。通过空间平移(如延时)构建两个子阵列,使得它们之间的关系具有旋转不变性。然后,通过对子阵列数据进行最小二乘拟合,可以得到信号源的角频率估计,进一步转换为DOA估计。 2. 常规ESPRIT算法实现 在描述中提到的`common_esprit_method1.m`和`common_esprit_method2.m`是两种不同的普通ESPRIT算法实现。它们可能在实现细节上略有差异,比如选择子阵列的方式、参数估计的策略等。MATLAB代码通常会包含预处理步骤(如数据归一化)、子阵列构造、旋转不变性矩阵的建立、最小二乘估计等部分。通过运行这两个文件,可以比较它们在估计精度和计算效率上的异同。 3. TLS_ESPRIT算法 TLS(Total Least Squares)ESPRIT是对普通ESPRIT的优化,它考虑了数据噪声的影响,提高了估计的稳健性。在TLS_ESPRIT算法中,不假设数据噪声是高斯白噪声,而是采用总最小二乘准则来拟合数据。这使得算法在噪声环境下表现更优。`TLS_esprit.m`文件应该包含了TLS_ESPRIT算法的完整实现,包括TLS估计的步骤和旋转不变性矩阵的改进处理。 在实际应用中,选择合适的ESPRIT变体取决于系统条件,例如噪声水平、信号质量以及计算资源。通过MATLAB实现,研究者和工程师可以方便地比较不同算法的效果,并根据需要进行调整和优化。同时,这些代码也为教学和学习DOA估计提供了一个直观的平台,有助于深入理解ESPRIT算法的工作原理。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值