animal.eat编译看左边编译的时候会先看Animal里面有什么方法可以调用bark没有在Animal中所以调用会直接报错。运行看右边animal.speak()运行的时候看右边类型Animal和Dog都有这个方法但是new的时候是Dog类型的所以结果应该是汪汪汪对象引用转换问题向上转型是自动进行的而且是安全的如下class Animal {} class Dog extends Animal {} Dog dog new Dog(); Animal animal dog//自动向上转型但是向下转型需要手动进行并且存在风险。如果父类对象实际上并不是目标子类的实例在转型时就会抛出异常Animal animal new Animal();//需要改成Animal animal new dog() Dog dog Doganimal// 运行时抛出classCastException解決方式是需要使用instanceof检查:if animal instanceof Dog) { Dogdog Doganimal//只有确认animal是Dog的实例时才进行转型为什么用bigDecimal 不用double使用BigDecimal可以确保精确的十进制数值计算避免了使用double可能出现的舍入误差。需要注意的是在创建BigDecimal对象时应该使用字符串作为参数而不是直接使用浮点数值以避免浮点数精度丢失。怎么把一个对象从一个jvm转移到另一个jvm?使用序列化和反序列化将对象序列化为字节流并将其发送到另一个VM然后在另一个VM中反序列化字节流恢复对象。这可以通过 Java 的 ObjectOutputStream 和 ObjectlnputStream 来实现。使用消息传递机制利用消息传递机制比如使用消息队列如RabbitMQ、Kafka或者通过网络套接字进行通信将对象从一个VM发送到另一个。这需要自定义协议来序列化对象并在另一个VM中反序列化。使用远程方法调用RPC)可以使用远程方法调用框架如gRPC来实现对象在不同JVM之间的传输。远程方法调用可以让你在分布式系统中调用远程MM上的对象的方法。使用共享数据库或缓存将对象存储在共享数据库如MySQL、PostgreSQL或共享缓存如Redis)中让不同的MM可以访问这些共享数据。这种方法适用于需要共享数据但不需要直接传输对象的场景。序列化和反序列化让你自己实现你会怎么做?Java 默认的序列化虽然实现方便但却存在安全漏洞、不跨语言以及性能差等缺陷。无法跨语言Java序列化目前只适用基于Java语言实现的框架其它语言大部分都没有使用Java的序列化框架也没有实现Java序列化这套协议。因此如果是两个基于不同语言编写的应用程序相互通信则无法实现两个应用服务之间传输对象的序列化与反序列化。容易被攻击Java序列化是不安全的我们知道对象是通过在ObjectlnputStream上调用readObject0方法进行反序列化的这个方法其实是一个神奇的构造器它可以将类路径上几乎所有实现了Serializable 接口的对象都实例化。这也就意味着在反序列化字节流的过程中该方法可以执行任意类型的代码这是非常危险的。序列化后的流太大序列化后的二进制流大小能体现序列化的性能。序列化后的二进制数组越大占用的存储空间就越多存储硬件的成本就越高。如果我们是进行网络传输则占用的带宽就更多这时就会影响到系统的吞吐量。我会考虑用主流序列化框架比如FastJson、Protobuf来替代Java 序列化。如果追求性能的话Protobuf序列化框架会比较合适Protobuf 的这种数据存储格式不仅压缩存储数据的效果好在编码和解码的性能方面也很高效。Protobuf 的编码和解码过程结合.proto文件格式加上 Protocol Buffer独特的编码格式只需要简单的数据运算以及位移等操作就可以完成编码与解码。可以说 Protobuf 的整体性能非常优秀。有一个学生类想按照分数排序再按照学号排序应该怎么做学生类实现Comparable接口重写compareTo方法使用时直接用Collections.sort(Student);即可public class Student implements ComparableStudent { private int id; private int score; //构造方法和其他属性、方法省略 override public int compareTo(Student other) { if (this.score ! other.score) { return Integer.compare(other.score, this.score); } else { return Integer.compare(this.idother.id);// 如果 } } } ListStudent students new ArrayList();//添加学生对象到列表中 Collections.sort(students);volatile和sychronized如何实现单例模式public class SingleTon { // volatile 关键字修饰变量 防止指令重排序 private static volatile SingleTon instance null; private SingleTon(){} public static SingleTon getInstance(){ if(instance null){ //同步代码块只有在第一次获取对象的时候会执行到第二次及以后访问时instance变量均非null故不会往下执行了 直接返回啦 synchronized(SingleTon.class){ if(instance null){ instance new SingleTon(); } } } return instance; } }代理模式和适配器模式有什么区别目的不同代理模式主要关注控制对对象的访问而适配器模式则用于接口转换使不兼容的类能够一起工作。结构不同代理模式一般包含抽象主题、真实主题和代理三个角色适配器模式包含目标接口、适配器和被适配者三个角色。应用场景不同代理模式常用于添加额外功能或控制对对象的访问适配器模式常用于让不兼容的接口协同工作。介绍一下策略模式和责任链模式分别用在哪些场景?策略模式定义一系列算法把它们一个个封装起来并且使它们可相互替换。从而让算法可独立于使用它的客户而变化。假设你正在开发一个电商网站的支付模块。用户可以选择支付宝、微信支付或者银行卡支付。每种支付方式的底层逻辑比如调用的API、加密方式、参数构造都完全不同但对于调用支付功能的上层业务逻辑来说它只需要调用一个统一的“支付”方法即可无需关心具体是哪种支付。这就是策略模式的用武之地。我们把每种支付方式支付宝、微信都封装成一个独立的“策略”类它们都遵循一个共同的接口。上层业务代码通过这个共同的接口来调用支付功能并可以在运行时根据用户的选择动态地切换不同的策略。所以策略模式适用场景如下当一个系统需要动态地在几种算法中选择一种时。当一个对象有很多行为不想使用大量的if-else或switch-case语句来选择时。当你希望算法的变化不会影响到使用它的客户端时。责任链模式核心思想是为请求创建一个接收者对象的链。对请求的发送者和接收者进行解耦让多个对象都有机会处理这个请求。请求沿着链传递直到链上的一个对象处理它为止。想象一下公司里的请假审批流程。一个员工要请假他首先会把请假条交给自己的直属经理。如果请假天数很短比如1天经理自己就能批准。如果天数较长比如5天经理没有权限就需要把请假条上报给部门总监。总监也有自己的审批权限上限如果超过了就需要继续上报给总经理。在这个过程中请假条请求就在一条由经理-总监-总经理接收者链上传递直到某个角色接收者能够处理它。发送请假条的员工客户端并不知道最终是谁批准了他的假他只需要把请求提交给链的第一个节点经理即可。所以责任链模式适用场景总结当有多个对象可以处理同一个请求但具体由哪个对象处理需要在运行时决定时。当你希望请求的发送者和接收者解耦不直接通信时。当你需要动态地指定和修改处理一个请求的对象集合时。Native方法解释一下在Java中native方法是一种特殊类型的方法它允许Java代码调用外部的本地代码即用C、C或其他语言编写的代码。native关键字是Java语言中的一种声明用于标记一个方法的实现将在外部定义。在Java类中native方法看起来与其他方法相似只是其方法体由native关键字代替没有实际的实现代码。例如:public class NativeExample { public native void nativeMethod(); }要实现native方法你需要完成以下步骤:1.生成JNI头文件使用javah工具从你的Java类生成C/C的头文件这个头文件包含了所有native方法的原型。2.编写本地代码使用C/C编写本地方法的实现并确保方法签名与生成的头文件中的原型匹配。3.编译本地代码将C/C代码编译成动态链接库DLL在Windows上共享库SO在Linux上)4.加载本地库在Java程序中使用System.loadLibraryO方法来加载你编译好的本地库这样VM就能找到并调用native方法的实现了。