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还有非常多的方法将在以后章节展现

      目录
      相关文章
      |
      6天前
      |
      存储 缓存 Oracle
      Java I/O流面试之道
      NIO的出现在于提高IO的速度,它相比传统的输入/输出流速度更快。NIO通过管道Channel和缓冲器Buffer来处理数据,可以把管道当成一个矿藏,缓冲器就是矿藏里的卡车。程序通过管道里的缓冲器进行数据交互,而不直接处理数据。程序要么从缓冲器获取数据,要么输入数据到缓冲器。
      Java I/O流面试之道
      |
      2天前
      |
      存储 缓存 Java
      大厂面试必看!Java基本数据类型和包装类的那些坑
      本文介绍了Java中的基本数据类型和包装类,包括整数类型、浮点数类型、字符类型和布尔类型。详细讲解了每种类型的特性和应用场景,并探讨了包装类的引入原因、装箱与拆箱机制以及缓存机制。最后总结了面试中常见的相关考点,帮助读者更好地理解和应对面试中的问题。
      17 4
      |
      3天前
      |
      存储 Java 程序员
      Java基础的灵魂——Object类方法详解(社招面试不踩坑)
      本文介绍了Java中`Object`类的几个重要方法,包括`toString`、`equals`、`hashCode`、`finalize`、`clone`、`getClass`、`notify`和`wait`。这些方法是面试中的常考点,掌握它们有助于理解Java对象的行为和实现多线程编程。作者通过具体示例和应用场景,详细解析了每个方法的作用和重写技巧,帮助读者更好地应对面试和技术开发。
      26 4
      |
      13天前
      |
      算法 Java
      JAVA 二叉树面试题
      JAVA 二叉树面试题
      13 0
      |
      12天前
      |
      监控 安全 Java
      在 Java 中使用线程池监控以及动态调整线程池时需要注意什么?
      【10月更文挑战第22天】在进行线程池的监控和动态调整时,要综合考虑多方面的因素,谨慎操作,以确保线程池能够高效、稳定地运行,满足业务的需求。
      91 38
      |
      10天前
      |
      安全 Java
      java 中 i++ 到底是否线程安全?
      本文通过实例探讨了 `i++` 在多线程环境下的线程安全性问题。首先,使用 100 个线程分别执行 10000 次 `i++` 操作,发现最终结果小于预期的 1000000,证明 `i++` 是线程不安全的。接着,介绍了两种解决方法:使用 `synchronized` 关键字加锁和使用 `AtomicInteger` 类。其中,`AtomicInteger` 通过 `CAS` 操作实现了高效的线程安全。最后,通过分析字节码和源码,解释了 `i++` 为何线程不安全以及 `AtomicInteger` 如何保证线程安全。
      java 中 i++ 到底是否线程安全?
      |
      4天前
      |
      存储 设计模式 分布式计算
      Java中的多线程编程:并发与并行的深度解析####
      在当今软件开发领域,多线程编程已成为提升应用性能、响应速度及资源利用率的关键手段之一。本文将深入探讨Java平台上的多线程机制,从基础概念到高级应用,全面解析并发与并行编程的核心理念、实现方式及其在实际项目中的应用策略。不同于常规摘要的简洁概述,本文旨在通过详尽的技术剖析,为读者构建一个系统化的多线程知识框架,辅以生动实例,让抽象概念具体化,复杂问题简单化。 ####
      |
      5天前
      |
      Java 开发者
      在Java多线程编程的世界里,Lock接口正逐渐成为高手们的首选,取代了传统的synchronized关键字
      在Java多线程编程的世界里,Lock接口正逐渐成为高手们的首选,取代了传统的synchronized关键字
      23 4
      |
      5天前
      |
      消息中间件 供应链 Java
      掌握Java多线程编程的艺术
      【10月更文挑战第29天】 在当今软件开发领域,多线程编程已成为提升应用性能和响应速度的关键手段之一。本文旨在深入探讨Java多线程编程的核心技术、常见问题以及最佳实践,通过实际案例分析,帮助读者理解并掌握如何在Java应用中高效地使用多线程。不同于常规的技术总结,本文将结合作者多年的实践经验,以故事化的方式讲述多线程编程的魅力与挑战,旨在为读者提供一种全新的学习视角。
      25 3
      |
      11天前
      |
      安全 Java
      在 Java 中使用实现 Runnable 接口的方式创建线程
      【10月更文挑战第22天】通过以上内容的介绍,相信你已经对在 Java 中如何使用实现 Runnable 接口的方式创建线程有了更深入的了解。在实际应用中,需要根据具体的需求和场景,合理选择线程创建方式,并注意线程安全、同步、通信等相关问题,以确保程序的正确性和稳定性。