• Java基础


    Java中的多态是什么

    1.多态概念:

    答:多态指的是相同类型的变量在调用同一个方法呈现出多种不同的行为特征即一种事物有多种存在形式,如男人和女人是两种不同的特征,但他们类型都是人。

    2.多态存在的三个必要条件:

    (1)继承

    (2)重写

    (3)父类引用指向子类对象,如:List list = new ArrayList<>();

    3.多态的优点:

    (1)消除对象之间的耦合性

    (2)可替换性

    (3)可扩充性

    (4)接口性

    (5)灵活性

    (6)简化性

    Java中变量,代码块,构造器之间执行顺序是怎么样的

    1.Java类中各元素初始化的原则是:

    答:先初始化静态的,再初始化动态部分;先初始化父类部分,后初始化子类部分;先初始化变量,再初始化代码块和构造器。

    2.Java中变量,代码块,构造器执行顺序是:

    public class Foo {
        public Foo(String word) {
            System.out.println(word);
        }
    }
    public class Base {
    static Foo staticInstance = new Foo("1---Base类的静态成员变量staticInstance");

    static {
    System.out.println("2---Base类的静态代码块执行了");
    }

    Foo foo = new Foo("5---Base类的普通成员变量instance");

    {
    System.out.println("6---Base类的动态代码块执行了");
    }

    Base() {
    System.out.println("7---Base类的构造器方法执行了");
    }
    }
    public class Child extends Base {
        static Foo staticInstance = new Foo("3---Child类的静态成员变量staticInstance");
    
        static {
            System.out.println("4---Child类的静态代码块执行了");
        }
    
        Foo instance = new Foo("8---Child类的普通成员变量instance");
    
        {
            System.out.println("9----Child类的动态代码块执行了");
        }
    
        Child() {
            System.out.println("10---Child类的构造器方法执行了");
        }
    
        public static void main(String[] args) {
            Child child = new Child();
        }
    }

    输出:

    1---Base类的静态成员变量staticInstance
    2---Base类的静态代码块执行了
    3---Child类的静态成员变量staticInstance
    4---Child类的静态代码块执行了
    5---Base类的普通成员变量instance
    6---Base类的动态代码块执行了
    7---Base类的构造器方法执行了
    8---Child类的普通成员变量instance
    9----Child类的动态代码块执行了
    10---Child类的构造器方法执行了

    3.小结:

    (1)父类的静态成员变量(如果是第一次加载类)

    (2)父类的静态代码块(如果是第一次加载类)

    (3)子类的静态成员变量(如果是第一次加载类)

    (4)子类的静态代码块(如果是第一次加载类)

    (5)父类的普通成员变量

    (6)父类的动态代码块

    (7)父类的构造器方法

    (8)子类的普通成员变量

    (9)子类的动态代码块

    (10)子类的构造器方法

    final关键字有哪些作用

    答:被final修饰的类不能被继承(且类中所有方法隐式被final修饰),被final修饰的方法不能被重写,被final修饰的变量不可以被改变。

    Integer类会进行缓存么

    1.例子:

    public static void main(String[] args) {
        Integer a = new Integer(127);
        Integer b = Integer.valueOf(127);
        Integer c = Integer.valueOf(127);
        Integer d = Integer.valueOf(128);
        Integer e = Integer.valueOf(128);
        System.out.println(a == b);
        System.out.println(b == c);
        System.out.println(d == e);
    }

    输出:

    false
    true
    false

    2.解析:

    (1)通过new Interger()创建Interger对象,每次返回全新的Integer对象。

    (2)通过Interger.valueOf()创建Interger对象,如果值在-128到127之间,会返回缓存的对象(初始化时)。

    3.类似的还有:

    (1)Integer:128~127

    (2)Byte:128~127

    (3)Short:128~127

    (4)Long:128~127

    (5)Character:0~127

    4.源码:

    Integer类中有一个静态内部类IntegerCach,在加载Integer类时会同时加载IntegerCache类,IntegerCache类的静态代码块中会创建值为-128到127的Integer对象,缓存到cache数组中,之后调用

    Integer.valueOf方法时,判断使用有缓存的Integer对象,有则返回,无则调用new Integer()创建。

    //Integer类中
    public static Integer valueOf(int i) {
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
    }
    
    private static class IntegerCache {
        static final int low = -128;
        static final int high;
        static final Integer cache[];
    
        static {
            // high value may be configured by property
            int h = 127;
            String integerCacheHighPropValue =
                    sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
            if (integerCacheHighPropValue != null) {
                try {
                    int i = parseInt(integerCacheHighPropValue);
                    i = Math.max(i, 127);
                    // Maximum array size is Integer.MAX_VALUE
                    h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
                } catch( NumberFormatException nfe) {
                    // If the property cannot be parsed into an int, ignore it.
                }
            }
            high = h;
    
            cache = new Integer[(high - low) + 1];
            int j = low;
            for(int k = 0; k < cache.length; k++)
                cache[k] = new Integer(j++);
    
            // range [-128, 127] must be interned (JLS7 5.1.7)
            assert IntegerCache.high >= 127;
        }
    
        private IntegerCache() {}
    }

    抽象类有哪些特点

    1.概念:

    答:从多个具体的类中抽象出来的父类叫做抽象类,抽象类就像是一个模板。

    2.抽象类特点:

    (1)抽象类可以包含抽象方法

    注:抽象方法与普通方法的区别在于,抽象类不提供抽象方法的实现,由继承抽象类的子类实现抽象方法。

    (2)抽象类不能实例化

    注:也正因为包含抽象方法,抽象类不能被实例化,由子类实例化。抽象类的构造器不能用于创建实例,是仅提供给子类调用的。除此以外,抽象类跟普通类一样,可以拥有成员变量,普通方法,构造器,初始化块,内部类,枚举等。

    (3)抽象类可以被继承

    注:继承抽象类的子类如果实现了所有抽象方法,那么可以作为普通类使用,否则也只能作为抽象类。

    (4)抽象类和抽象方法必须用abstract关键字修饰。

    abstract class 类名()
    public abstract void eat();

    (5)抽象类不一定有抽象方法,有抽象方法的类一定是抽象类或者是接口。

    3.抽象类与接口和其他类的区别:

      与具体类比较:

    (1)抽象类不能直接实例化,并且对抽象类使用 new 运算符会导致编译时错误。虽然一些变量和值在编译时的类型可以是抽象的,但是这样的变量和值必须或者为 null,或者含有对非抽象类的实例的引用(此非抽象类是从抽象类派生的)。

    (2)允许(但不要求)抽象类包含抽象成员。

    (3)抽象类不能被密封。

      与接口比较:

    抽象类表示该类中可能已经有一些方法的具体定义,但是接口就仅仅只能定义各个方法的界面(方法名,参数列表,返回类型),并不关心具体细节。

    String,StringBuffer和StringBuilder之间的区别是什么

    1.可变性:

    (1)String:String是一个不可变类,任何对String改变都是会产生一个新的String对象,所以String类是使用final来进行修饰的。

    (2)StringBuffer:StringBuffer是可变类,和线程安全的字符串操作类,任何对它指向的字符串的操作都不会产生新的对象。每个StringBuffer对象都有一定的缓冲区容量,当字符串大小没有超过容量时,不会分配新的容量,当字符串大小超过容量时,会自动增加容量 。

    (3)StringBuilder:可变类,速度更快。

    2.线程安全:

    (1)StringBuffer:线程安全。

    (2)StringBuilder:线程不安全。

    3.执行效率:

    当频繁对字符串进行修改时,使用String会生成一些临时对象,多一些附加操作,执行效率降低。

    stringA = StringA + "2";
    //实际上等价于
    {
      StringBuffer buffer = new StringBuffer(stringA)
      buffer.append("2");
      return buffer.toString();
    }

    且StringBuffer里是线程安全的,因为里面用synchronized关键字加了锁,额外的加锁会带来性能上的损耗,所以StringBuilder比StringBuffer更快。

    4.适合场景:

    (1)StringBuffer:多线程操作字符串。

    (2)StringBuilder:单线程操作字符串。

    5.小结:

    (1)如果要操作少量的数据用 String;

    (2)多线程操作字符串缓冲区下操作大量数据 StringBuffer;

    (3)单线程操作字符串缓冲区下操作大量数据 StringBuilder。

    编译型编程语言,解释型编程语言,伪编译型语言的区别是什么

     1.概念:

    编译型编程语言:使用专门的编译器,针对特定的平台,将高级语言源代码一次性的编译成可被该平台硬件执行的机器码,并包装成该平台所能识别的可执行性程序的格式。

    解释型编程语言:使用专门的解释器对源程序逐行解释成特定平台的机器码并立即执行。

    伪编译型语言:编译时只编译成中间代码,将中间代码和解释器一起打包成可执行文件。然后执行时使用解释器将中间代码解析成二进制代码。Visual Basic属于此类。

    2.特点:

    编译型编程语言:在编译型语言写的程序执行之前,需要一个专门的编译过程,把源代码编译成机器语言的文件,如exe格式的文件,以后要再运行时,直接使用编译结果即可,如直接运行exe文件。

    因为只需编译一次,以后运行时不需要编译,所以编译型语言执行效率高。

    解释型编程语言:解释型语言不需要事先编译,其直接将源代码解释成机器码并立即执行,所以只要某一平台提供了相应的解释器即可运行该程序。

    3.小结:

    编译型编程语言:

    (1)一次性的编译成平台相关的机器语言文件,运行时脱离开发环境,运行效率高;

    (2)与特定平台相关,一般无法移植到其他平台;

    (3)现有的C、C++、Objective等都属于编译型语言。

    解释型编程语言:

    (1)解释型语言每次运行都需要将源代码解释成机器码并执行,效率较低;

    (2)只要平台提供相应的解释器,就可以运行源代码,所以可以方便源程序移植;

    (3)解释型语言有Java、JavaScript、VBScript、Perl、Python、Ruby、MATLAB等。

    Java中的访问控制符有哪些

    答:public(公共)、protected(保护)、default(默认)、 private(私有)。

    Java的构造器有哪些特点

    1.名字与类名同

    2.构造器函数无返回值

    3.构造器总是伴随new操作而被调用,且不能对一个已经存在的对象调用构造函数来达到重置实例域的目的。

    Java中的内部类是怎么样的

    1.概念:

    把类定义在另一个类的内部,该类就被称为内部类。

    2.内部类的访问规则:

    (1)可以直接访问外部类(指包含内部类的那个类)的成员,包括私有。

    (2)外部类要想访问内部类成员,必须创建对象。

    3.必要性:

    有的时候你可能有这样一种需求:对一个类(假设它为MyClass.java)创建一个和它相关的类(假设它是Part.java),但因为Part.java和MyClass之间的联系“紧密”且“单一”,导致我们在这种情况下,不希望增加一个额外的兄弟类,而希望能将Part.java的数据隐藏在MyClass.java内部,于是这个时候内部类就出现了。

    Java中的注解是什么

    注解是一种元数据,提供与程序有关的数据但是不属于程序本身。

    hashCode()和equals()方法一起重写的原因

    前景提要:

    hashCode的默认实现不一定是返回内存地址,以OpenJDK为例,hashCode的默认计算方法有5种,有返回随机数的,有返回内存地址,具体采用哪一种计算方法取决于运行时库和JVM的具体实现。

    1.hashCode()概念:

    hashCode()的作用是获取哈希码,也称为散列码,它实际上是返回一个int整数,这个哈希码的作用是确定该对象在哈希表中的索引位置。且hashCode()定义在Object()类中,这就意味着Java中的任何类都包含有hashCode()。

    2.hashCode()方法的作用有哪些:

    (1)对对象做散列。为了将一组键值对均匀地存储在一个数组中,HashMap对key的hashCode进行计算得到一个hash值,用hash对数组长度取模,得到数组下标,将键值对存储在数组下标对应的链表下。

    (2)快速判断对象是否相等。hashCode()相等,equals()不一定相等;equals()相等,hashCode()一定相等

    3.hashCode()和equals()之间的关系:

    答:如果两个对象相等,则hashcode()一定也是相同的。两个对象相等,对两个对象分别调用 equals 方法都返回 true。但是,两个对象有相同的hashcode值,它们也不一定是相等的 。因此equals()方法被覆盖过,则hashCode()方法也必须被覆盖。

    4.为什么相同的hashCode()但也不一定相等:

    答:因为 hashCode() 所使用的杂凑算法也许刚好会让多个对象传回相同的杂凑值。越糟糕的杂凑算法越容易碰撞,但这也与数据值域分布的特性有关(所谓碰撞也就是指的是不同的对象得到相同的

    hashCode。如果 HashSet 在对比的时候,同样的 hashcode 有多个对象,它会使用 equals() 来判断是否真的相同。也就是说 hashcode 只是用来缩小查找成本。

     

    ==和equals的区别

    区别:

    "=="是判断两个变量或实例是不是指向同一个内存空间。

    "equals"是判断两个变量或实例所指向的内存空间的值是不是相同。

    小结:

    //Object类源码
    public
    boolean equals(Object obj) { return (this == obj); }

    默认情况下也就是从超类Object继承而来的equals方法与‘==’是完全等价的,比较的都是对象的内存地址,但我们可以重写equals方法,使其按照我们的需求的方式进行比较,如String类重写了equals

    方法,使其比较的是字符的序列,而不再是内存地址。 

    重写和重载的区别

    1.概念:

    重写:重写是父类与子类之间的多态性,实际是父类通过子类进行重新定义。

    重载:重载是指相同函数名的函数,但函数的参数个数不同或者类型不同,调用的时候根据函数的参数来区别不同的函数。

    2.多态性:

    重写:父类和子类之间多态性的表现,运行时起作用。

    重载:类中多态性的表现,编译时起作用。

    谈一谈栈和队列

    栈:

    1.概念:

    是限制对元素的插入(push)和删除(pop)只能在一个位置上进行的表,该位置是表的末端,叫做栈的栈顶(top)。像桶一样,Last In First Out,后进先出。

    队列:

    1.概念:

    是先进先出的线性表,队尾插入,队头出队。

    参考:https://www.cnblogs.com/sang-bit/p/11757553.html

    IO和NIO的区别(暂)

    1.面向的对象不同:NIO面向块(面向缓冲区),IO面向流。

    2.阻塞模式不同:NIO有阻塞和非阻塞两种模式,IO只有阻塞模式。

    3.选择器:NIO有选择器,IO没有。

    接口和抽象类的区别

    接口:

    1.接口使用interface修饰。

    2.一个类可以实现多个接口。

    3.接口不能被实例化。

    抽象类:

    1.抽象类使用abstract修饰。

    2.抽象类不能被实例化。

    3.抽象类里一般都有抽象方法(当然也可以没有)。

    int和Integer的自动拆箱/装箱相关问题

    先聊聊int和Integer:

    1.Integer是int的包装类,int则是java的一种基本数据类型。

    2.Integer变量必须实例化后才能使用,而int变量不需要。

    3.Integer实际是对象的引用,当new一个Integer时,实际上是生成一个指针指向此对象;而int则是直接存储数据值。 

    4.Integer的默认值是null,int的默认值是0。

    自动装箱:

    Integer a = 10;

    因为Integer有自动装箱功能,通过反编译就会发现class文件是:

    Integer a = Integer.valueOf(10);

    以上就是自动装箱的原理。

    自动拆箱:

    int b = a;

    反编译生成的class文件是:

    int b = a.intVlaue();
    /**
    public int intValue() {
    return value;
    }
    */

    注:算术运算会触发自动拆箱

    谈一谈关于常量池

    try、catch、finally都有return语句时执行哪个

    先说结论:先执行try中的return,但不会真正返回,有异常会执行catch中的return,但也不会真正返回,如果finally里有return,则会返回finally里的return,如果没有则返回之前的。

    注意:

    1.不管有没有异常,finally都会执行。

    2.try和catch里有return,finally也会执行。

    3.finally里中有return的话,是一定被return的。

     

    参考链接:

    1.https://github.com/NotFound9/interviewGuide/blob/master/docs/JavaBasic.md#Java%E4%B8%AD%E7%9A%84%E5%A4%9A%E6%80%81%E6%98%AF%E4%BB%80%E4%B9%88%EF%BC%9F

    2.https://blog.csdn.net/itchuxuezhe_yang/article/details/89966303

    3.https://www.cnblogs.com/myseries/p/12490118.html

    4.https://github.com/Snailclimb/JavaGuide/blob/master/docs/java/Java%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86.md#129-hashcode%E4%B8%8E-equals

  • 相关阅读:
    Navicat Premium15安装与激活
    JDK13.0.1安装与环境变量的配置(Win10平台为例)
    Linux系统手动安装Firefox浏览器
    Debian 9.5 解决中文显示乱码
    debian 安装后需做的几件事
    Windows10 Linux子系统安装图形化界面的两种方法及其对比
    线程池大小设置,CPU的核心数、线程数的关系和区别,同步与堵塞完全是两码事
    Java学习笔记八(反射)
    高速排序法(一)
    Java深入
  • 原文地址:https://www.cnblogs.com/wencheng9012/p/13590045.html
Copyright © 2020-2023  润新知