Java中的String实例化、Annotation注解类、继承的多态和Object类(附带相关面试题)

简介: 1.java中String两种实例化对象2.Annotation注解类 3.继承的多态 4.Object类

1.java中String两种实例化对象

在Java中String并不是一个数据类型,而是引用数据类型

创建方式的区别

作为特殊类,其创建方式有两种

String strA= "mldn";
String str = "mldn";
String strB = new String("mldn");

image.gif

下面介绍其区别:

image.gif编辑

strA在堆上创建mldn空间,而strB的实例化中有new 即新创建一个空间内容也是mldn,而strc内容是mldn与strA是一致的,所以不会再分配新的空间,而是直接将strC的栈地址直接指向strA的堆地址

*面试题new String("a") + new String("b") 会创建几个对象?

对象1:new StringBuilder()

对象2:new String("a")

对象3:常量池中的"a"

对象4:new String("b")

对象5:常量池中的"b"

深入剖析:StringBuilder中的toString():

对象6:new String("ab")

强调一下,toString()的调用,在字符串常量池中,没有生成"ab"

面试题 String str="i"与 String str=new String(“i”)一样吗?

String str="i"会将起分配到常量池中,常量池中没有重复的元素,如果常量池中存中i,就将i的地址赋给变量,如果没有就创建一个再赋给变量。

String str=new String(“i”)会将对象分配到堆中,即使内存一样,还是会重新创建一个新的对象。


2.Annotation注解类

1.@Override 准确性覆写类

覆写发生在子类中有一个和父类相同方法名、相同参数列表和相同返回类型的方法时。在一般情况下,通过子类对象调用该方法时,会直接调用子类中的方法。这是因为子类方法覆盖了父类方法,所以会优先调用子类的方法实现。

然而,如果在某些情况下出现错误,可能会导致错误地调用父类的方法,例如:

    1. 子类方法的签名与父类方法不一致:如果子类中定义的方法签名与父类的方法签名不完全匹配,例如参数列表不同,那么不会发生准确性覆写,而是子类创建了一个新的方法,和父类的方法没有关联。此时,通过子类对象调用方法时,会调用到父类的方法。
    2. 在子类中使用了super关键字:子类中可以使用super关键字调用父类的方法,即使发生了准确性覆写。在这种情况下,通过super关键字调用的是父类的方法,而不是子类的方法。

    所以通过@Override就可以避免出现上述问题从而正常调用子类

    package Example82;
    class father{
        public void function(){
            System.out.println("执行父亲函数的");
        }
    }
    class son extends father{
        @Override
        public void function(){
            System.out.println("利用@Override准确性覆写执行子函数");
        }
    }
    public class javaDemo {
        public static void main(String[] args) {
        son s = new son();
        s.function();
        }
    }

    image.gif

    image.gif编辑

    2.@Deprecated过期声明注解

    当一个类可能已经不符合生产的需求后,但是如果随便删除这个类可能会导致整个程序结构的不稳定从而出错,所以java中就有@Deprecated过期声明注解,在用该注解后某个类或者某个方法将不再建议使用。如果调用则会在方法上加上删除线

    image.gif编辑

    *面试题: 在 Java 中,什么时候用重载,什么时候用重写?

    (1)重载是多态的集中体现,在类中,要以统一的方式处理不同类型数据的时候,可以用重载。

    (2)重写的使用是建立在继承关系上的,子类在继承父类的基础上,增加新的功能,可以用重写。

    (3)简单总结:

    重载是多样性,重写是增强剂;

    目的是提高程序的多样性和健壮性,以适配不同场景使用时,使用重载进行扩展;

    目的是在不修改原方法及源代码的基础上对方法进行扩展或增强时,使用重写;

     


    3.多态

    1.向上转型

    向上转型 即大范围转到小范围 比如 动物和狗,动物就是父类,狗是子类,这种往下细分的操作就叫向上转型

    父类 name = new 子类();

    为什么要出现向上转型

      1. 统一接口:通过向上转型,可以将不同子类的对象都当作父类类型来处理。这样可以使用统一的接口对这些对象进行操作,简化了代码的编写和维护。如果有多个子类,使用向上转型可以避免针对每个子类都编写相似的代码段,提高了代码的重用性。
      2. 扩展性:通过向上转型,可以更加方便地扩展代码,增加新的子类,而无需修改已有的代码。这是因为向上转型使得代码与具体子类解耦,如果需要增加一个新的子类,只需要修改创建对象的部分,而不需要修改其他已经存在的代码逻辑。
      3. 可替换性:通过向上转型,可以实现对子类对象的替换。即使使用父类引用变量来引用子类对象,仍然可以调用子类中重写的方法,实现对父类引用的灵活使用。这使得程序在后续的维护和扩展过程中更加方便,可以根据需要轻松地切换不同的子类实现。
      package Example84;
      class Animal {
          public void sound() {
              System.out.println("Animal makes sound");
          }
      }
      class Dog extends Animal {
          @Override
          public void sound() {
              System.out.println("Dog barks");
          }
          public void playFetch() {
              System.out.println("Dog plays fetch");
          }
      }
      class Cat extends Animal {
          @Override
          public void sound() {
              System.out.println("Cat barks");
          }
          public void playFetch() {
              System.out.println("Cat plays fetch");
          }
      }
      public class javaDemo {
          public static void main(String[] args) {
              Animal animal = new Dog(); // 向上转型
              animal.sound();
              animal = new Cat();
              animal.sound();
          }
      }

      image.gif

      image.gif编辑

      通过向上转型,我们可以实例化一个 Animal 对象,并且通过该对象引用子类对象,从而灵活地切换它们之间的关系。然而,向上转型有一个重要限制,即我们只能调用父类中定义的方法,或者子类中覆盖了的方法。这意味着,一些子类特有的功能将无法直接通过父类引用调用。例如,在上述代码中,我们可以使用 animal.sound() 调用 Animal 类中的 sound 方法,但无法使用 animal.playFetch() 调用 Dog 或 Cat 类特有的 playFetch 方法。

      为此就有了向下转型

      2.向下转型

      条件:必须要在向上转型的基础上才能进行向下转型,否则父类与子类无关联的情况下无法进行联系

      案例代码:

      package Example84;
      class Animal {
          public void sound() {
              System.out.println("Animal makes sound");
          }
      }
      class Dog extends Animal {
          @Override
          public void sound() {
              System.out.println("Dog barks");
          }
          public void playFetch() {
              System.out.println("Dog plays fetch");
          }
      }
      public class javaDemo {
          public static void main(String[] args) {
              Animal animal = new Dog(); // 向上转型
              ((Dog) animal).playFetch();//强制向下转型
              Dog dog = (Dog) animal;//第二种强制向下转型
              dog.playFetch();
          }
      }

      image.gif

      image.gif编辑

      3.instanceof关键字(判断是否能向下转型)

      当使用了向上转型后,将子类的实例赋值给父类的引用变量时,就会丧失对子类特有方法的直接访问能力。此时,如果想要调用子类的方法,就需要进行安全转型,即使用 instanceof 检查对象是否为某个特定类型,并在确认类型后进行强制转型。

      在这种情况下,如果我们直接调用子类的方法而没有进行安全转型,会导致编译错误,因为编译器只知道引用变量的静态类型,而无法确定运行时实际对象的类型。这样的错误可能会导致程序在运行时抛出 ClassCastException 异常,因为尝试将父类引用转换为子类类型是非法的。

      用法:  实例化对象名称 instanceof 类  返回boolean类型的值

      package Example84;
      class Animal {
          public void sound() {
              System.out.println("Animal makes sound");
          }
      }
      class Dog extends Animal {
          @Override
          public void sound() {
              System.out.println("Dog barks");
          }
      }
      public class javaDemo {
          public static void main(String[] args) {
             Animal animal = new Animal();
              System.out.println(animal instanceof Animal);
              System.out.println(animal instanceof Dog);
             Animal animal1 = new Dog();
              System.out.println(animal1 instanceof Animal);
              System.out.println(animal1 instanceof Dog);
          }
      }

      image.gif

      image.gif编辑

      具体应用

      image.gif编辑


      4.Object类

      1.概述

      1.在Java中,Object类是所有类的根类,也可以说是所有类的父类。它定义了一些通用的方法,如equals()hashCode()toString()等。当我们定义一个类时,如果没有显式指定它的父类,那么默认情况下该类会直接继承自Object类。因此,你可以将其视为所有类的隐式父类。

      然而,并不是所有类型的数据都可以被向上转型为Object类型。在Java中,基本类型(如intbooleanchar等)是不能直接向上转型为Object类型的。相反,只有引用类型(如类、接口等)可以被向上转型为Object类型。

      在Java中,当我们将一个引用类型的对象向上转型为Object类型时,它实际上已经是Object类型的对象了,但是我们只能通过Object类型的引用变量访问 Object 类中定义的方法,无法直接调用原始类型的方法。如果我们想要调用原始类型的方法,就需要进行向下转型(即安全强制类型转换)。

      因此,尽管Object类可以作为所有类的父类,但并不意味着它可以接受所有类型的数据。只有引用类型可以被向上转型为Object类型,而基本类型不能。同时,为了调用子类特有的方法,还需要进行向下转型。

      2.Object的toString方法

      package Example84;
      class Animal extends Object{
          public void sound() {
              System.out.println("Animal makes sound");
          }
      }
      class Dog extends Animal {
          @Override
          public void sound() {
              System.out.println("Dog barks");
          }
          public void fectch(){
              System.out.println("Dog fectch");
          }
          @Override
          public String toString(){
              return "直接打印一个类,其实是调用了Object类中的toString函数";
          }
      }
      public class javaDemo {
          public static void main(String[] args) {
             Animal animal = new Dog();
              System.out.println(animal);
          }
      }

      image.gif

      image.gif编辑

      面试题:hashcode是什么?有什么作用?

      Java中Object有一个方法:

      public native int hashcode();

      (1)hashcode()方法的作用

      1.hashcode()方法主要配合基于散列的集合(相关知识在java的类集中进行学习)一起使用,比如HashSet、HashMap、HashTable。

      当集合需要添加新的对象时,先调用这个对象的hashcode()方法,得到对应的hashcode值,实际上hashmap中会有一个table保存已经存进去的对象的hashcode值,如果table中没有改hashcode值,则直接存入,如果有,就调用equals方法与新元素进行比较,相同就不存了,不同就存入。

      (2)equals和hashcode的关系

      如果equals为true,hashcode一定相等;

      如果equals为false,hashcode不一定不相等;

      如果hashcode值相等,equals不一定相等;

      如果hashcode值不等,equals一定不等;

      (3)重写equals方法时,一定要重写hashcode方法

      Object还有非常多的方法将在以后章节展现

      目录
      相关文章
      |
      17天前
      |
      监控 Java 应用服务中间件
      高级java面试---spring.factories文件的解析源码API机制
      【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置、起步依赖和内嵌服务器等特性,极大地简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是spring.factories文件的解析源码API机制。
      49 2
      |
      6天前
      |
      Java 程序员
      Java社招面试题:& 和 && 的区别,HR的套路险些让我翻车!
      小米,29岁程序员,分享了一次面试经历,详细解析了Java中&和&&的区别及应用场景,展示了扎实的基础知识和良好的应变能力,最终成功获得Offer。
      31 14
      |
      22天前
      |
      存储 算法 Java
      大厂面试高频:什么是自旋锁?Java 实现自旋锁的原理?
      本文详解自旋锁的概念、优缺点、使用场景及Java实现。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
      大厂面试高频:什么是自旋锁?Java 实现自旋锁的原理?
      |
      24天前
      |
      存储 缓存 Java
      大厂面试必看!Java基本数据类型和包装类的那些坑
      本文介绍了Java中的基本数据类型和包装类,包括整数类型、浮点数类型、字符类型和布尔类型。详细讲解了每种类型的特性和应用场景,并探讨了包装类的引入原因、装箱与拆箱机制以及缓存机制。最后总结了面试中常见的相关考点,帮助读者更好地理解和应对面试中的问题。
      47 4
      |
      4月前
      |
      存储 Java
      【IO面试题 四】、介绍一下Java的序列化与反序列化
      Java的序列化与反序列化允许对象通过实现Serializable接口转换成字节序列并存储或传输,之后可以通过ObjectInputStream和ObjectOutputStream的方法将这些字节序列恢复成对象。
      |
      2月前
      |
      算法 Java 数据中心
      探讨面试常见问题雪花算法、时钟回拨问题,java中优雅的实现方式
      【10月更文挑战第2天】在大数据量系统中,分布式ID生成是一个关键问题。为了保证在分布式环境下生成的ID唯一、有序且高效,业界提出了多种解决方案,其中雪花算法(Snowflake Algorithm)是一种广泛应用的分布式ID生成算法。本文将详细介绍雪花算法的原理、实现及其处理时钟回拨问题的方法,并提供Java代码示例。
      79 2
      |
      2月前
      |
      JSON 安全 前端开发
      第二次面试总结 - 宏汉科技 - Java后端开发
      本文是作者对宏汉科技Java后端开发岗位的第二次面试总结,面试结果不理想,主要原因是Java基础知识掌握不牢固,文章详细列出了面试中被问到的技术问题及答案,包括字符串相关函数、抽象类与接口的区别、Java创建线程池的方式、回调函数、函数式接口、反射以及Java中的集合等。
      31 0
      |
      4月前
      |
      存储 安全 Java
      这些年背过的面试题——Java基础及面试题篇
      本文是技术人面试系列Java基础及面试题篇,面试中关于Java基础及面试题都需要了解哪些内容?一文带你详细了解,欢迎收藏!
      |
      4月前
      |
      XML 存储 JSON
      【IO面试题 六】、 除了Java自带的序列化之外,你还了解哪些序列化工具?
      除了Java自带的序列化,常见的序列化工具还包括JSON(如jackson、gson、fastjson)、Protobuf、Thrift和Avro,各具特点,适用于不同的应用场景和性能需求。
      |
      4月前
      |
      Java
      【Java基础面试三十七】、说一说Java的异常机制
      这篇文章介绍了Java异常机制的三个主要方面:异常处理(使用try、catch、finally语句)、抛出异常(使用throw和throws关键字)、以及异常跟踪栈(异常传播和程序终止时的栈信息输出)。