首页 > 编程语言 >1.Java基础

1.Java基础

时间:2024-01-14 22:01:00浏览次数:28  
标签:Singleton 父类 Java 对象 子类 基础 序列化 方法

1.1JAVA中的几种基本数据类型是什么,各自占用多少字节。

  Java中有八种基本数据类型,分别是byte(1bit)、boolean(不占用)char(2bit)、short(2bit)、int(4bit)、long(8bit)、float(4bit)、double(8bit)。

1.2 String类能被继承吗,为什么。

  String类不能被继承,因为其被final关键字声明,不允许被继承。

1.3 String,Stringbuffer,StringBuilder的区别。

  1. String是一个不可变的字符串,线程安全;
  2. StringBuffer和StringBuilder都是可变的字符串,与String主要的区别是允许修改其内容,StringBuffer其内部方法是同步的,线程安全;
  3. StringBuilder内部方法不是同步的,线程不安全;由于StringBuffer内部方法是通过synchronized关键字修饰,在获取锁和释放锁消耗性能,因此在操作效率上低于StringBuilder。

1.4 ArrayList和LinkedList有什么区别。

  1. ArrayList底层是由动态数组构建的,LinkedList底层是链表结构
  2. ArrayList由于其数组结构并实现了RandomAccess接口,可以实现随机访问,而LinkedList不能
  3. LinkedList在头插、尾插元素(某些情况)效率上比ArrayList效率高
  4. ArrayList相对于LinkedList占用更少的内存,由于LinkedList需要存储前驱和后驱指针

1.5 讲讲类的实例化顺序,比如父类静态数据,构造函数,父类字段,子类静态数据,构造函数,字段,当new的时候,他们的执行顺序。类静态数据----->子类静态数据----->父类字段----->父类构造方法----->子类字段----->子类构造方法

  • 静态初始化块和字段只在类中初始化一次。

1.6 用过哪些Map类,都有什么区别,HashMap是线程安全的吗,并发下使用的Map是什么,他们内部原理分别是什么,比如存储方式,hashcode,扩容,默认容量等。

  • 使用过HashMap、ConcurrentHashMap;HashMap是线程不安全的,ConcurrentHashMap是线程安全的。
  • HashMap和ConcurrentHashMap底层结构都是数组+链表/红黑树组成的。
  • HashMap默认容量为16,当集合中元素超过容量的0.75时,进行扩容,每次扩容增长为原来的两倍。为减少哈希冲突,需要将通过hashcode()方法计算得到的hash值与数组长度进行取余操作,将存储的元素散列到各个位置。如果除数为2的幂次,那么取余操作相当于除数减一的与操作,采用二进制与操作,能够提升运算效率。
  • ConcurrentHashMap默认容量和扩容机制同HashMap,在JDK1.7时,其由Segment数组和HashEntry组成来保证多个线程同步,在JDK1.8以后,通过CAS操作和Node数组以及synchronized关键字保证每个Node数组之间的安全性(只要不产生hash冲突)。

1.7 JAVA8的ConcurrentHashMap为什么放弃了分段锁,有什么问题吗,如果你来设计,你如何设计。

  JDK1.7的ConcurrentHashMap是利用Segment和HashEntry保证多个线程访问,Segment实现了Lock接口,是一种重量级锁,当数据分布不均匀时,会加剧锁竞争。使用CAS和局部重排序能够更细粒度实现线程同步,还能减少Segment分配的锁对象开销,提高性能。

1.8 有没有有顺序的Map实现类,如果有,他们是怎么保证有序的。

  TreeMap就是有顺序的Map实现类,它是通过实现Comparator的compareTo方法保证有序

1.9 抽象类和接口的区别,类可以继承多个类么,接口可以继承多个接口么,类可以实现多个接口

区别:

  • 接口强调对行为的约束,类强调的时从属关系;
  • 一个类只能继承一个父类,但是可以实现多个接口
  • 接口中的成员变量只能通过private static final修饰且必须初始化复制或构造函数赋值,抽象类中的成员变量是default类型,可由其子类重新定义或修改。

  类不能继承多个类,接口可以继承多个接口,类可以实现多个接口

1.10 继承和聚合的区别在哪。

  • 继承关注的是类之间的继承和扩展关系,而聚合关注的是类之间的组合和包含关系
  • 继承是一种强耦合关系,因为子类紧密依赖于父类的实现。而聚合是一种较弱的耦合关系,因为成员类可以独立于容器类存在和改变
  • 继承通常用于表示类之间的层次结构和抽象与具体的关系,而聚合用于表示类之间的组合和整体与部分的关系

1.11 IO模型有哪些,讲讲你理解的nio ,他和bio,aio的区别是啥,谈谈reactor模型。

  • IO模型有NIO(同步非阻塞)、BIO(同步阻塞)、AIO(异步非阻塞)三种IO模型
  • BIO是指应用程序发起Read调用,会一直阻塞,直到内核把数据复制到应用层
  • NIO是指同步非阻塞,它可以通过多次发起Read调用不阻塞,但当内核将数据拷贝到应用层是阻塞的
  • AIO基于事件和回调机制实现,应用操作后直接返回,当后台处理完,操作系统通知响应线程进行后续操作。

reactor模型

reactor模型是一种处理大量并发I/O请求的设计模式,常用于构建高性能服务器

  1. 单个或多个输入处理器(Reactor):负责监听和分发来自客户端的事件或请求到相应的处理器
  2. 事件处理器(Handler):负责处理实际的业务逻辑,如读取数据、执行计算、写回响应等。
  3. 多路复用:Reactor使用I/O多路复用技术(如select、poll、epoll等)来监听多个连接,而不是为每个连接分配一个线程。
  4. 事件驱动:系统基于事件驱动,当有新的事件发生时,Reactor会将事件分发给对应的处理器进行处理

1.12 反射的原理,反射创建类实例的三种方式是什么。

反射是指运行时分析类,执行类中方法的机制

反射创建实例的方法分为已知具体类和不知具体类

已知类使用类.class方法

不知类

  1. Class.forName(“全路径”)方法
  2. 对象实例instance.getClass
  3. 类加载ClassLoader.getSystemClassLoader.loaderClass(“全路径”)方法

1.13 反射中,Class.forName和ClassLoader区别 。

  Class.forName()和ClassLoader都用于加载类,但它们之间还是存在区别:

  • Class.forName()是一个静态方法,ClassLoader是一个类
  • Class.forName()和ClassLoader类都可能在加载类时出现ClassNotFoundException,但ClassLoader拥有更多加载选项和更细粒度控制。
  • Class.foName()加载的类如果没有初始化,那么它会通过Class.forName()进行初始化,ClassLoader默认不会初始化类,除非反射调用newIInstance()方法或其他初始化方法。

1.14 描述动态代理的几种实现方式,分别说出相应的优缺点。

JDK动态代理,代理接口,Proxy类的newProxyInstance()方法通过类加载器、接口、以及InvocationHandler对象以及重写InvocationHandler的invoke()方法实现动态代理

优点

  • 简单易用,只需重写InvocationHandler的invoke方法即可
  • 无需引入额外库
  • 目标类需要实现接口,才可创建代理对象

缺点

  • 目标类没有实现接口,无法使用JDK动态代理
  • final方法和private方法,无法进行代理

CGLIB动态代理,代理类。通过字节码技术,子类覆盖父类实现代理

优点

  • 无需类实现接口就能实现动态代理
  • 功能更强大,可代理final和private方法

缺点:

  • 需引入额外库(CG)
  • 相对于JDK代理更复杂,性能较差
  • 通过生成子类方法实现,可能会产生继承的副作用。

1.15 动态代理与cglib实现的区别。

  1. JDK动态代理是通过实现InvocationHandler的invoke方法结合反射增强被代理类,再Proxy.newProxyInstance()方法根据接口和InvocationHandler对象产生代理对象完成代理功能;
  2. CGLIB动态代理是通过实现MethodInterceptor接口中的intercept()方法结合反射增强被代理类,通过Enhancer.create()方法产生代理对象完成代理功能。

1.16 为什么CGlib方式可以对接口实现代理。

  其实CGlib是通过对接口的实现类实现动态代理,而不是对接口进行代理

1.17 final的用途。

  final可以用来修饰成员变量、类,方法。被final修饰的变量一旦赋值不能被修改。被final修饰的类不能被继承,被final修饰的方法不能被重写。

1.18 写出三种单例模式实现 。

饿汉

public class Singleton{
    private Singleton(){}
    private static Singleton singleton = new Singleton();
    private static Singleton getSingleton(){
        return singleton;
    }
}

懒汉式(线程不安全)

public class Singleton{
    private Singleton(){}
    private static Singleton singleton;
    private static Singleton(){
        if(singleton == null){
             singleton = new Singleton();
        }
        return singleton;
    }
}

双重检测懒汉式(线程安全)

public class Singleton{
    private Singleton(){}
    private static Singleton singleton;
    private static Singleton(){
        if(singleton == null){
             sychronized(){
                  if(singleton == null){
                       singleton = new Singleton();
                  }
             }
        }
        return singleton;
    }
}

 枚举懒汉式

public enum Singleton{
    INSTANCE;
}

1.19 如何在父类中为子类自动完成所有的hashcode和equals实现?这么做有何优劣。

   在Java中,我们不能直接在父类中为子类自动完成所有hashCode和equals方法的实现,因为每个类可能具有不同的相等性和哈希码计算逻辑。但可以创建一个通用基类或抽象类,提供默认的、基于对象状态的hashCode和equals方法,并鼓励子类重写这些方法以适应自己的需求。

优点

  • 父类提供的通用方法做模板,减少重复代码
  • 子类可以通过父类得到基本的equals方法和hashcode方法

缺点

  • 父类无法预知子类所有的字段,因此无法提供准确的equals方法和hashcode方法
  • 子类有不相等性规则时,不正确的继承会导致违反equals和hashcode约定

1.20 请结合OO设计理念,谈谈访问修饰符public、private、protected、default在应用设计中的作用。

  1. public

    • public访问修饰符表示成员(类、方法或变量)对所有其他类都是可见的,不受包或类层次结构的限制
  2. private:访问修饰符表示成员仅对其所在的类可见,对外部类完全不可见。常用于封装类的内部属性,只暴露必要的操作接口。

  3. protected

    • protected访问修饰符允许成员在同一个包内或者子类中可见,但在包外的其他类中不可见。
    • 保护成员对于实现继承关系下的复用和扩展特别有用。子类能够访问父类的受保护成员,以便于进行重写(override)或者使用父类的非公共功能
    • 使用protected关键字有助于实现OO中的继承和多态特性,同时保持一定程度的封装。
  4. default(无修饰符,也称为package-private):

    • 默认访问修饰符没有显式指定,成员仅在同一个包内的其他类中可见,而在包外则不可见。
    • 它支持同一包内的类之间共享某些功能,但不鼓励跨包间的直接访问,从而降低了不同包之间不必要的依赖关系。
    • 在包级私有成员的帮助下,可以构建更模块化的系统,其中各个包相对独立,相互之间只通过公共API进行通信。

1.21 深拷贝和浅拷贝区别。

  • 深拷贝和浅拷贝都是通过clone()方法拷贝父类引用。
  • 深拷贝是拷贝原对象的整个对象,包括原对象的内部对象。
  • 浅拷贝只是拷贝了原对象的内部对象的引用地址,浅拷贝对象和原对象还是共用同一个内部对象。

1.22 数组和链表数据结构描述,各自的时间复杂度。

  • 数组是内存连续的,支持随机访问,插入删除效率较链表低
  • 链表是内存不连续的,不支持随机访问,插入删除效率较数组高

1.23 error和exception的区别,CheckedException,RuntimeException的区别。

  • error和Exception有一个共同的父类Throwable。
  • error是应用程序无法处理的错误,不建议通过catch捕获,如虚拟机异常,Exception是程序可以处理的异常,可以使用catch进行捕获。
  • 异常分为受检查异常(CheckedException)和不受检查异常(RuntimeException及其子类)。
  • CheckedException是受检查异常,一定要捕获,不然无法编译通过
  • RuntimeException及其子类被称为非受检查异常,不捕获也能编译通过

1.24 请列出5个运行时异常。

  • NullPointerException(空指针错误)
  • IllegalArgumentException(参数错误比如方法入参类型错误)
  • NumberFormatException(字符串转换为数字格式错误,IllegalArgumentException的子类)
  • ArrayIndexOutOfBoundsException(数组越界错误)
  • ClassCastException(类型转换错误)

1.25 在自己的代码中,如果创建一个java.lang.String类,这个类是否可以被类加载器加载?为什么。

  不可以,String类是Java的核心类,由BootstrapClassLoader加载。Java类的加载遵循双亲委派加载机制。

1.26 说一说你对java.lang.Object对象中hashCode和equals方法的理解。在什么场景下需要重新实现这两个方法。

  hashcode和equal方法都是用来判断两个对象是否相等,其中先进行hashcode判断,如果不等,则两个对象不相等,反之进一步通过equals方法比较两个对象内存地址是否相等(Object默认),实际应用中一一判断两个对象的属性值是否全部相等,进而判断两个对象是否相等。

场景

  • 类作为哈希表的键或值
  • 基于字段判断对象是否相等
  • 一旦重写equals方法,必须重写hashcode方法,保证两个相等的对象hash值相等

1.27 在jdk1.5中,引入了泛型,泛型的存在是用来解决什么问题。

  泛型在编译时,通过参数表示类型,再具体使用(运行)时实现类型转换。

1.28 这样的a.hashcode() 有什么用,与a.equals(b)有什么关系。

  求对象的hash值,在使用equals比较两个对象是否相等时,会先计算两个对象的hashcode是否相等,如果不等则两个对象不相等,如果相同,则进一步通过equals方法比较两个对象的内存地址判断两个对象是否相等(Object默认),实际应用是一一判断两个对象的属性值是否全部相等

1.29 有没有可能2个不相等的对象有相同的hashcode。

  有可能,因为两个对象并不是具有相同的hashcode就是同一对象,这还需要通过equals()方法比较两个对象中内存地址相等(Object默认),实际应用中一一判断两个对象的全部属性值是否相等,才能决定两个对象是否相等。

1.30 Java中的HashSet内部是如何工作的。

  HashSet用于存储唯一且不重复的元素,当一个元素加入HashSet时,会先根据哈希算法计算该元素的hash值,如果hash值与HashSet中已加入元素的hash值不同,则加入到HashSet中;反之则进一步通过元素的equals方法计算它们是否相等,如果相等则该元素已存在,不必加入HashSet中;反之则通过拉链法解决哈希冲突,将元素以链表或红黑树形式链接。

1.31 什么是序列化,怎么序列化,为什么序列化,反序列化会遇到什么问题,如何解决。

  序列化是将对象转换为二进制字节流进行数据传输。在Java中类可以通过实现Serializable接口实现序列化,也可以引入其他序列化协议进行序列化,如kryo、protobuf、Hession等。网络数据传输、文件存储、数据库、内存存储都是以二进制字节流流进行存储。如果我们需要将对象进行网络数据传输、文件、数据库、内存存储就需要进行序列化。

反序列化问题

安全问题:反序列化前需要对数据进行验证和过滤

兼容性问题:当对类中字段进行增删改时,序列化的类版本与运行时类版本不一致导致序列化异常或数据丢失;对于实现了Serializable但是没有自定义serialVersionUID的类,Java会自动生成一个序列化号,在改变类结构时容易出现序列化失败。

性能问题:大量数据反序列化会消耗大量内存和CPU资源,可通过分块读取和处理数据、合理设置缓冲区大小。

异常处理:在反序列化时会出现ClassNotFoundException、InvalidClassException(类格式错误或版本不匹配)、IOException,应妥善处理这些异常,保证序列化健壮性。

数据一致性问题:序列化包含无法持久化的引用(网络连接),反序列化会导致无效状态。

1.32 java8的新特性

  • lambda表达式:简洁方式定义匿名函数,提高代码可读性,简化集合流操作、事件处理
  • Stream流:简化集合的排序、过滤、映射、聚合操作
  • removeIf:简化集合中元素删除操作

标签:Singleton,父类,Java,对象,子类,基础,序列化,方法
From: https://www.cnblogs.com/kzf-99/p/17964272

相关文章

  • web基础协议
    一.web通信流程在开始学web服务器之前,需要先理解web通信协议,才能够更好的吸收其中精华。我们平时浏览⽹⻚的时候,会打开浏览器,输⼊⽹址后按下回⻋键,然后就会显示出你想要浏览的内容。在这个看似简单的⽤户⾏为背后,到底隐藏了些什么呢?浏览器本身是⼀个客户端,当你输⼊URL的时候,⾸先浏......
  • 学习JavaDay02
    常用的DOS命令盘符切换E:英文冒号查看当前目录下的所有文件dir切换目录cdchangedirectorycd..清理屏幕cls查看电脑IPipconfig打开应用calcmspaintnotepad文件操作md目录名rd目录名cd>文件名del文件名HelloWorld新建文件夹,存放代码新建一个Java文件......
  • 学习Java笔记 - Day2
    Java特性优势简单性:基于C,纯净版的C++面向对象:一切皆对象可移植性:Writeonce,runanywhere-跨平台高性能:及时编译,效率分布式:为网络分布式环境设计,可处理TCP/IP协议,通过URL,访问网络资源,相当于本地资源,简单。支持远程的方法调用。动态性:反射机制,有了动态性。多线程:看视频,......
  • HTML5基础之常见文本控制标识
    一、文本控制标记 1.标题标记 标题标记是指在网页文件中,以独立方式显现的标题内容,其后面的文字内容会在显示时会另起一行,在HTML中有6个级别(按从大到小分):  <h1><h2><h3>...<h6> 语法格式: <hn align="文字对齐方式">标题文本</hn>  (n=1,2,3,4,5,6)  a......
  • HTML5基础之结构元素
    结构元素  结构元素是将显示区域通过结构元素方式进行方位上的划分,以方便后续的管理或样式上的设置  提醒:结构划分,仅体现在标记上,在显示或功能上无区别(美化方面由后面的样式实现) 1.header元素 显示区域的头部,即网页显示区域的项部空间。 2.nav元素 用于定义......
  • [JAVA] Java泛型实践
    Java泛型实践泛型,即“参数化类型”。一提到参数,最熟悉的就是定义方法时有形参,然后调用此方法时传递实参。那么参数化类型怎么理解呢?顾名思义,就是将类型由原来的具体的类型参数化,类似于方法中的变量参数,此时类型也定义成参数形式(可以称之为类型形参),然后在使用/调用时传入具体的类......
  • 洛谷比赛【LGR-171-Div.3】深圳科创学院基础赛 #7 &「RHOI」Round 2 赛后总结
    洛谷比赛【LGR-171-Div.3】深圳科创学院基础赛#7&「RHOI」Round2赛后总结比赛链接:https://www.luogu.com.cn/contest/146495建议先看原题再看文章。A-Water(P10056)有\(n\)个杯子,每个杯子的容积是\(a\),且初始装有\(b\)体积水。你可以进行任意次操作,每次操作选择任......
  • 搜索学习笔记+杂题 (基础二 dfs/bfs的拓展)
    搜索杂题:博客中讲述的题的题单:戳我二、dfs/bfs的各种变式1、深搜深搜以指数级的时间复杂度闻名,稍不注意时间就会爆炸,所以一般会用到剪枝的技巧(这个技巧基本上是因题而异,需要平时的刷题与积累)。深搜同样也是一种可变性极高的算法(其实都可以不叫做一种算法,深搜已经是一种做题的......
  • 面向对象编程基础
    类和对象的区别和联系类是抽象的,概念的,代表一类事物,比如人类,猫类..,即它是数据类型.对象是具体的,实际的,代表一个具体事物,即是实例.类是对象的模板,对象是类的一个个体,对应一个实例属性,成员变量,字段成员变量=属性=field(字段)(即成员变量是用来表示属性的,统一叫属......
  • java于C配合
       虽然没有完成全部过程,最后卡在调用时报错,但还是记录下过程:1、创建java类,声明native方法packagecom.example.gpumonitor;publicclassGPUMonitor{static{System.loadLibrary("gpumonitor");//加载对应平台的动态链接库}publicnativeS......