选择题

  • 构造方法 必须满足以下语法规则:
    (1)方法名必须与类名相同;
    (2)不要声明返回类型;
    (3)不能被static、final、synchronized、abstract和native修饰;
    (4)构造方法用final和abstract修饰没有意义。
    (5)在单例模式下,构造方法是声明为private的。错误
    (6)构造方法可以不用显式的定义,虚拟机会提供一个默认的无参构造方法。
  • String
    String str1=“hello”; 这样创建字符串是存在于常量池中
    String str2=new String(“hello”); str2存在于堆中,
    ==是验证两个对象是否是一个(内存地址是否相同)
    用+拼接字符串时会创建一个新对象再返回。
  • instance是java的二元运算符,用来判断他左边的对象是否为右面类(接口,抽象类,父类)的实例.
  • 在Java线程状态转换
    在这里插入图片描述
  • java的数据类型分为两大类:基本类型和引用类型.
    基本类型只能保存一些常量数据,引用类型除了可以保存数据,还能提供操作这些数据的功能;
    为了操作基本类型的数据,java也对它们进行了封装, 得到八个类,就是java中的基本类型的封装类;他们分别是:
    八种基本类型: byte short int long float double char boolean
    对应的包装类 : Byte Short Integer Long Float Double Character Boolean
  • List和Set
    Set 不能有重复的元素,且是无序的,要有空值也就只能有一个。因为它不允许重复。 L ist 可以有重复元素,且是有序的,要有空值也可以有多个,因为它可重复 。
  • this()和super()
    this()才必须是构造函数中的第一个可执行语句,用this调用语句并不需要。
    this()和super()为构造方法,作用是在JVM堆中构建出一个对象。因此避免多次创建对象,同一个方法内只能调用一次this()或super()。同时为了避免操作对象时对象还未构建成功,需要this()和super()的调用在第一行实现【以此来创建对象】,防止异常。
  • 内部类与外部类
    ( 1 )对于外部类而言,它也可以使用访问控制符修饰,但外部类只能有两种访问控制级别: public 和默认。因为外部类没有处于任何类的内部,也就没有其所在类的内部、所在类的子类两个范围,因此 private 和 protected 访问控制符对外部类没有意义。
    ( 2 )内部类的上一级程序单元是外部类,它具有 4 个作用域:同一个类( private )、同一个包( protected )和任何位置( public )。
    ( 3 ) 因为局部成员的作用域是所在方法,其他程序单元永远不可能访问另一个方法中的局部变量,所以所有的局部成员都不能使用访问控制修饰符修饰。
    在这里插入图片描述
  • Java语言提供了很多修饰符,大概分为两类:访问权限修饰符 ; 2. 非访问权限修饰符。
    访问权限修饰符
    public:共有访问。对所有的类都可见。
    protected:保护型访问。对同一个包可见,对不同的包的子类可见。
    default:默认访问权限。只对同一个包可见,注意对不同的包的子类不可见。
    private:私有访问。只对同一个类可见,其余都不见。
    缺省访问修饰符只在本包中可见,在外包中不可见
    非访问权限修饰符
    static 修饰符,用来创建类方法和类变量。
    final 修饰符,用来修饰类、方法和变量,final 修饰的类不能够被继承,修饰的方法不能被继承类重新定义,修饰的变量为常量,是不可修改的。
    abstract 修饰符,用来创建抽象类和抽象方法。
    synchronized 用于多线程的同步。
    volatile 修饰的成员变量在每次被线程访问时,都强制从共享内存中重新读取该成员变量的值。而且,当成员变量发生变化时,会强制线程将变化值回写到共享内存。这样在任何时刻,两个不同的线程总是看到某个成员变量的同一个值。
    transient:序列化的对象包含被 transient 修饰的实例变量时,java 虚拟机(JVM)跳过该特定的变量。
  • 比大小
    浮点数是不直接进行判等比较的,因为浮点数存在精度问题。要比较两个浮点数,一般的比较方法是设定一个精度,当二者的差小于某个精度时,认为二者相等。
    ==比较的是地址,只有同一个类才会返回true。
  • Spring依赖注入(DI)的三种方式,分别为:
    1. 接口注入
    2. Setter 方法注入
    3. 构造方法注入
  • append
    Java中的append( )方法其实是创建了一个新的数组,扩大了长度,将需要添加的字符串给复制到这个新的数组中。
    JAVA中Stringbuffer有append( )方法:
      Stringbuffer其实是动态字符串数组 ,append( )是往动态字符串数组添加,跟“xxxx”+“yyyy”相当那个‘+’号 ,跟String不同的是Stringbuffer是放一起的,String1+String2 和Stringbuffer1.append(“yyyy”)虽然打印效果一样,但在内存中表示却不一样,String1+String2 存在于不同的两个地址内存,Stringbuffer1.append(Stringbuffer2)放再一起。
    StringBuffer是线程安全的,多用于多线程。
  • java集合框架
    在这里插入图片描述
  • 对接口以及抽象实现类认识
    LinkedList是继承自AbstractSequentialList(抽象类,实现了List接口)的,并且实现了List接口。
    AbstractSet是实现了Set接口的,本身是一个抽象类。继承自AbstractCollection(抽象类,实现了Collection接口)。
    HashSet是继承自AbstractSet,实现了Set接口。
    WeakMap不存在于java集合框架的。只有一个叫做WeakHashMap(继承自AbstractMap)。
  • 接口(interface)
    可以说成是抽象类的一种特例,接口中的所有方法都必须是抽象的。接口中的方法定义默认为public abstract类型,接口中的成员变量类型默认为public static final。另外,接口和抽象类在方法上有区别:
    1.抽象类可以有构造方法,接口中不能有构造方法。
    2.抽象类中可以包含非抽象的普通方法,接口中的所有方法必须都是抽象的,不能有非抽象的普通方法。
    3.抽象类中可以有普通成员变量,接口中没有普通成员变量
    4.抽象类中的抽象方法的访问类型可以是public,protected和默认类型
    5.抽象类中可以包含静态方法,接口中不能包含静态方法
    6.抽象类和接口中都可以包含静态成员变量,抽象类中的静态成员变量的访问类型可以任意,但接口中定义的变量只能是public static final类型,并且默认即为public static final类型
    7.一个类可以实现多个接口,但只能继承一个抽象类。二者在应用方面也有一定的区别:接口更多的是在系统架构设计方法发挥作用,主要用于定义模块之间的通信契约。而抽象类在代码实现方面发挥作用,可以实现代码的重用,例如,模板方法设计模式是抽象类的一个典型应用,假设某个项目的所有Servlet类都要用相同的方式进行权限判断、记录访问日志和处理异常,那么就可以定义一个抽象的基类,让所有的Servlet都继承这个抽象基类,在抽象基类的service方法中完成权限判断、记录访问日志和处理异常的代码,在各个子类中只是完成各自的业务逻辑代码。
  • 枚举类型
    创建枚举类型要使用 enum 关键字,枚举类型的每一个值都将映射到 protected Enum(String name, int ordinal) 构造函数中。简单来说就是枚举类型中的枚举值都会对应调用一次构造函数。
    枚举中的构造函数是私有类,也就是无法再外面创建enum。枚举类构造方法只能加private修饰符(或不加),因为枚举类本身已经是构造好的,不允许再被外部构造 。
  • JAVA的初始化顺序:
    父类的静态成员初始化>父类的静态代码块>子类的静态成员初始化>子类的静态代码块>父类的代码块>父类的构造方法>子类的代码块>子类的构造方法
  • 执行的先后顺序
    子类A继承父类B, A a = new A(); 则父类B构造函数、父类B静态代码块、父类B非静态代码块、子类A构造函数、子类A静态代码块、子类A非静态代码块。
    父类B静态代码块->子类A静态代码块->父类B非静态代码块->父类B构造函数->子类A非静态代码块->子类A构造函数。
    静态代码块优先于主方法,且只执行一次 。
    常见算法时间复杂度O(1): 表示算法的运行时间为常O(n): 表示该算法是线性算
    O(㏒2n): 二分查找算法
    O(n2): 对数组进行排序的各种简单算法,例如直接插入排序的算法。
    O(n3): 做两个n阶矩阵的乘法运算
    O(2n): 求具有n个元素集合的所有子集的算法
    O(n!): 求具有N个元素的全排列的算法
    优<---------------------------<劣
    O(1)<O(㏒2n)<O(n)<O(n2)<O(2n)
    时间复杂度按数量级递增排列依次为:常数阶O(1)、对数阶O(log2n)、线性阶O(n)、线性对数阶O(nlog2n)、平方阶O(n2)、立方阶O(n3)、……k次方阶O(nk)、指数阶O(2n)。
  • 方法重载(overload):
    1.必须是同一个类
    2方法名(也可以叫函数)一样
    3参数类型不一样或参数数量不一样
  • 方法的重写(override)两同两小一大原则:
    方法名相同,参数类型相同,返回类型要相同
    子类抛出异常小于等于父类方法抛出异常,
    子类访问权限大于等于父类方法访问权限。
  • ArrayList和LinkedList的区别:
    1.ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构。
    2.对于随机访问get和set,ArrayList觉得优于LinkedList,因为LinkedList要移动指针。
    3.对于新增和删除操作add和remove,LinedList比较占优势,因为ArrayList要移动数据。
  • ArrayList和LinkedList的性能比较:
    1.对ArrayList和LinkedList而言,在列表末尾增加一个元素所花的开销都是固定的。对ArrayList而言,主要是在内部数组中增加一项,指向所添加的元素,偶尔可能会导致对数组重新进行分配;而对LinkedList而言,这个开销是统一的,分配一个内部Entry对象。
    2.在ArrayList的中间插入或删除一个元素意味着这个列表中剩余的元素都会被移动;而在LinkedList的中间插入或删除一个元素的开销是固定的。
    3.LinkedList不支持高效的随机元素访问。
    4.ArrayList的空间浪费主要体现在在list列表的结尾预留一定的容量空间,而LinkedList的空间花费则体现在它的每一个元素都需要消耗相当的空间
    可以这样说:当操作是在一列数据的后面添加数据而不是在前面或中间,并且需要随机地访问其中的元素时,使用ArrayList会提供比较好的性能;当你的操作是在一列数据的前面或中间添加或删除数据,并且按照顺序访问其中的元素时,就应该使用LinkedList了。
    j
  • ava关键字都是小写
    在这里插入图片描述
  • Java标识符命名规范是:
    1)只能包含字母a-zA-Z,数字0-9,下划线_和美元符号$;
    2)首字母不能为数字;
    3)关键字和保留字不能作为标识符。
  • sleep()和wait()
    Java中的多线程是一种抢占式的机制,而不是分时机制。抢占式的机制是有多个线程处于可运行状态,但是只有一个线程在运行。
    共同点 :
    1.他们都是在多线程的环境下,都可以在程序的调用处阻塞指定的毫秒数,并返回。
    2.wait()和sleep()都可以通过interrupt()方法 打断线程的暂停状态 ,从而使线程立刻抛出InterruptedException。
    如果线程A希望立即结束线程B,则可以对线程B对应的Thread实例调用interrupt方法。如果此刻线程B正在wait/sleep/join,则线程B会立刻抛出InterruptedException,在catch() {} 中直接return即可安全地结束线程。
    需要注意的是,InterruptedException是线程自己从内部抛出的,并不是interrupt()方法抛出的。对某一线程调用 interrupt()时,如果该线程正在执行普通的代码,那么该线程根本就不会抛出InterruptedException。但是,一旦该线程进入到 wait()/sleep()/join()后,就会立刻抛出InterruptedException 。
    不同点 :
    1.每个对象都有一个锁来控制同步访问。Synchronized关键字可以和对象的锁交互,来实现线程的同步。
    sleep方法没有释放锁,而wait方法释放了锁,使得其他线程可以使用同步控制块或者方法。
    2.wait,notify和notifyAll只能在同步控制方法或者同步控制块里面使用,而sleep可以在任何地方使用
    3.sleep必须捕获异常,而wait,notify和notifyAll不需要捕获异常
    4.sleep是线程类(Thread)的方法,导致此线程暂停执行指定时间,给执行机会给其他线程,但是监控状态依然保持,到时后会自动恢复。调用sleep不会释放对象锁。
    5.wait是Object类的方法,对此对象调用wait方法导致本线程放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象发出notify方法(或notifyAll)后本线程才进入对象锁定池准备获得对象锁进入运行状态。
  • Java把内存分成两种,一种叫做栈内存,一种叫做堆内存。
    在函数中定义的一些基本类型的变量和对象的引用变量都是在函数的栈内存中分配。当在一段代码块中定义一个变量时,java就在栈中为这个变量分配内存空间,当超过变量的作用域后,java会自动释放掉为该变量分配的内存空间,该内存空间可以立刻被另作他用。
    堆内存用于存放由new创建的对象和数组。在堆中分配的内存,由java虚拟机自动垃圾回收器来管理。在堆中产生了一个数组或者对象后,还可以在栈中定义一个特殊的变量,这个变量的取值等于数组或者对象在堆内存中的首地址,在栈中的这个特殊的变量就变成了数组或者对象的引用变量,以后就可以在程序中使用栈内存中的引用变量来访问堆中的数组或者对象,引用变量相当于为数组或者对象起的一个别名,或者代号。
    引用变量是普通变量,定义时在栈中分配内存,引用变量在程序运行到作用域外释放。而数组&对象本身在堆中分配,即使程序运行到使用new产生数组和对象的语句所在地代码块之外,数组和对象本身占用的堆内存也不会被释放,数组和对象在没有引用变量指向它的时候(比如先前的引用变量x=null时),才变成垃圾,不能再被使用,但是仍然占着内存,在随后的一个不确定的时间被垃圾回收器释放掉。这个也是java比较占内存的主要原因。
    实际上,栈中的变量指向堆内存中的变量,这就是Java中的指针。
    总结起来就是对象存储在堆内存,引用变量存储在栈内存。栈内存指向堆内存。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值