首页 > 编程语言 >给小白讲java中两大怪物,附带面试题!

给小白讲java中两大怪物,附带面试题!

时间:2023-06-08 22:33:08浏览次数:67  
标签:面试题 java 构造方法 附带 子类 System 父类 public out

类介绍

Java 程序是由若干个类组成的,类也是面向对象编程思想的具体实现。

以下为类的定义:

public class User {
    //私有属性
    private Long userId;
    private String name;
    private Integer age;
    // 构造方法
    public User() {
    }
    //有残构造方法
    public User(Long userId, String name, Integer age) {
        this.userId = userId;
        this.name = name;
        this.age = age;
    }

    //普通方法
    public void say() {
        System.out.println("hello world");
    }
    // 对外包装属性
    public String getName() {
        return this.name;
    }
}

关键字import的三种用法

单类型导入

当我们需要使用不同包下的类时,就需要使用 import 导入包或类,这个时候才能正常使用。例如,我们要使用java.util下的 ArrayList 就必须使用 import java.util.ArrayList,代码如下:

// 导入 ArrayList 类
import java.util.ArrayList;
class Test {
    public static void main(String[] args) {
        ArrayList list = new ArrayList();
    }
}
按需类型导入

如果我们在同一个类中使用了同一个包下面的较多类时候,就会使用按需类型导入。

// 用到了java.util包目录下的List、ArrayList和LinkedList类
//import java.util.ArrayList;
//import java.util.LinkedList;
//import java.util.List;
//如果不想类上有太多import,就可以直接import 包名.*
import java.util.*;
public class Test {
    public static void main(String[] args) {
        List list = new ArrayList<>();
        List list1 = new LinkedList();
    }
}

这个只是表象,其实也是一个一个的导入的,只是在代码层面看起来是一次性全部倒入了。

静态导入

import 还可以导入静态方法和静态域的功能,比如以下代码:

//**精准导入**
//直接导入具体的静态变量、常量、方法方法,注意导入方法直接写方法名不需要括号。
import static com.assignment.test.StaticFieldsClass.staticField;
import static com.assignment.test.StaticFieldsClass.staticFunction;

//或者使用如下形式:
//**按需导入**不必逐一指出静态成员名称的导入方式
//import static com.assignment.test.StaticFieldsClass.*;

public class StaticTest {
    public static void main(String[] args) {
        //这里直接写静态成员而不需要通过类名调用
        System.out.println(staticField);
        staticFunction();
    }
}

以上代码也可以顺利的执行,这也是 import 好玩的一个地方。

构造方法

构造方法也叫构造器或构造函数,它的作用是类在进行初始化的时候会调用对应的构造方法,比如以下代码:

public class User {
    //私有属性
    private Long userId;
    private String name;
    private Integer age;
    // 构造方法
    public User() {
    }
    //有参构造方法
    public User(Long userId, String name, Integer age) {
        this.userId = userId;
        this.name = name;
        this.age = age;
    }

    //普通方法
    public void say() {
        System.out.println("hello world");
    }
    public static void think() {
        System.out.println("thinking");
    }
    // 对外包装属性
    public String getName() {
        return this.name;
    }
构造方法五大原则
  1. 构造方法必须与类同名;
  2. 构造方法的参数可以没有或者有多个;
  3. 构造方法不能定义返回值(默认返回类型就是本类类型);
  4. 每个类可以有一个或多个构造方法;
  5. 构造方法总是伴随着 new 操作一起使用。

注意:如果勒种没有显示的定义构造方法,那么在编译的时候回默认为其添加一个无惨构造方法。构造方法实际开发中通常都是public修饰,还有就是我们想要单例的情况下搞成private修饰。

Object

Object 类是 Java 中的一个特殊类,它是所有类的父类,Java 中的类都直接或间接的继承自 Object 类。

Object 类的常用方法如下:

  • equals():对比两个对象是否相同
  • getClass():返回一个对象的运行时类
  • hashCode():返回该对象的哈希码值
  • toString():返回该对象的字符串描述
  • wait():使当前的线程等待
  • notify():唤醒在此对象监视器上等待的单个线程
  • notifyAll():唤醒在此对象监视器上等待的所有线程
  • clone():克隆一个新对象

关于更多 Object 的内容,如克隆(深克隆、浅克隆)、线程的几个常用方法wait、notify、notifyAll,对象比较,对象的hashCode值等。

继承

Java 中只支持单继承:即一个子类只能继承一个父类,而一个父类可以被多个子类继承。

每个人都只能有一个亲生父亲,一个父亲是可以有多个儿子的。

用法:使用 extends 关键字来实现类的继承,示例代码如下:

class Person {
    public void say() {
        System.out.println("hello");
    }
}
public class User extends Person {
    public static void main(String[] args) {
        Person user = new User();
        user.say();
    }
}

以上程序执行结果:hello

继承的注意点
  1. 单一继承性。(在Java中是不支持多继承的,通俗的说子类只能有一个父类,而父类可以有很多子类。)
  2. 支持多层继承。(继承可以一直传下去,子类有父类,父类又有父类...)
  3. 如果父类成员使用private修饰,那么子类不能被继承。(private只是对本类有效)
  4. 如果一个子类继承了父类的属性和方法还可以有自己特有的属性和方法。(不光有父类的属性(可继承的)和方法(可继承的),也有自己独有的属性和方法。)
  5. 当子类和父类的成员变量重名的时候,子类优先。(就近原则)
继承使用技巧
  • 将公共的变量或者方法提取到超类中;
  • 除非所有的方法都有继承的意义,否则不要使用继承;
  • 在方法覆盖时不要改变原有方法的预期行为。
  • 一般在写代码的时候发现代码中存在重复代码,需要向上抽取,考虑继承。
  • 当某个类的设计非常复杂的时候可以考虑继承
继承的优点
  • 代码的可重用性。
  • 使用继承可以轻松的定义子类。
  • 父类的属性和方法可以用于子类中(非private修饰)。
  • 设计应用程序变得更加简单。

设计模式中大量使用

比如:模板方法模式,就是采用继承,子类自己去实现自己的业务逻辑。

面试题

类与对象有哪些区别?

类是一个抽象的概念,是对某一事物的描述;而对象是类的实例,是实实在在存在的个体。

比如:“男人”就是一个类(一个概念),而老田(田维常)就是实实在在的一个“对象”。

注意:对象中又有类对象,即Class对象,但是类对象始终还是对象,不是类,这两个概念别搞混淆了。

Java 中可以多继承吗?

Java 中只能单继承,但可以实现多接口,并且支持多层继承。

Java 中为什么不能实现多继承?

答:从技术的实现角度来说,是为了降低编程的复杂性。假设 A 类中有一个 m() 方法,B 类中也有一个 m() 方法,如果 C 类同时继承 A 类和 B 类,那调用 C 类的 m() 方法时就会产生歧义,这无疑增加了程序开发的复杂性,为了避免这种问题的产生,Java 语言规定不能多继承类,但可以实现多接口。

覆盖和重载有哪些区别?

重写(Override)
  • 从字面上看,重写就是 重新写一遍的意思。其实就是在子类中把父类本身有的方法重新写一遍。子类继承了父类原有的方法,但有时子类并不想原封不动的继承父类中的某个方法,所以在方法名,参数列表,返回类型(除过子类中方法的返回值是父类中方法返回值的子类时)都相同的情况下, 对方法体进行修改或重写,这就是重写。但要注意子类函数的访问修饰权限不能少于父类的。
public class Father {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Son s = new Son();
        s.sayHello();
    }

    public void sayHello() {
        System.out.println("Hello");
    }
}

class Son extends Father{

    @Override
    public void sayHello() {
        // TODO Auto-generated method stub
        System.out.println("hello by ");
    }

}

重写 总结:

1.发生在父类与子类之间

2.方法名,参数列表,返回类型(除过子类中方法的返回类型是父类中返回类型的子类)必须相同

3.访问修饰符的限制一定要大于被重写方法的访问修饰符(public>protected>default>private)

4.重写方法一定不能抛出新的检查异常或者比被重写方法的更加宽泛的检查型异常

重载(Overload)
  • 在一个类中,同名的方法如果有不同的参数列表(参数类型不同、参数个数不同甚至是参数顺序不同)则视为重载。同时,重载对返回类型没有要求,可以相同也可以不同,但不能通过返回类型是否相同来判断重载。
public class Father {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Father s = new Father();
        s.sayHello();
        s.sayHello("wintershii");

    }

    public void sayHello() {
        System.out.println("Hello");
    }

    public void sayHello(String name) {
        System.out.println("Hello" + " " + name);
    }
}

重载 总结:1.重载Overload是一个类中多态性的一种表现 2.重载要求同名方法的参数列表不同(参数类型,参数个数甚至是参数顺序) 3.重载的时候,返回值类型可以相同也可以不相同。无法以返回型别作为重载函数的区分标准。

为什么方法不能根据返回类型来区分重载?

答:因为在方法调用时,如果不指定类型信息,编译器就不知道你要调用哪个方法了。比如,以下代码:

float max(int x,int y);
int max(int x,int y);
// 方法调用
max(1,2);

因为 max(1,2) 没有指定返回值,编译器就不知道要调用哪个方法了。

说说构造方法的特点有哪些?

答:构造方法的特征如下:

  • 构造方法必须与类名相同;
  • 构造方法没有返回类型(默认返回本类类型);
  • 构造方法不能被继承、覆盖、直接调用;
  • 类定义时提供了默认的无参构造方法;
  • 构造方法可以私有,外部无法使用私有构造方法创建对象。

构造函数能不能被覆盖?能不能被重载?

构造函数可以重载,但不能覆盖。

以下程序执行的结果是?

class ExecTest {
    public static void main(String[] args) {
        Son son = new Son();
    }
}
class Parent{
    {
        System.out.print("1");
    }
    static{
        System.out.print("2");
    }
    public Parent(){
        System.out.print("3");
    }
}
class Son extends Parent{
    {
        System.out.print("4");
    }
    static{
        System.out.print("5");
    }
    public Son(){
        System.out.print("6");
    }
}

结果是:251346

类加载顺序

整体

给小白讲java中两大怪物,附带面试题!_设计模式

细分

给小白讲java中两大怪物,附带面试题!_设计模式_02

以下程序执行的结果是?

class A {
    public int x = 0;
    public static int y = 0;
    public void m() {
        System.out.print("A");
    }
}
class B extends A {
    public int x = 1;
    public static int y = 2;
    public void m() {
        System.out.print("B");
    }
    public static void main(String[] args) {
        A myClass = new B();
        System.out.print(myClass.x);
        System.out.print(myClass.y);
        myClass.m();
    }
}

结果是:00B

注意:在 Java 语言中,变量不能被重写。

Java 中的 this 和 super 有哪些区别?

this 和 super 都是 Java 中的关键字,起指代作用,在构造方法中必须出现在第一行,它们的区别如下。

  • 基础概念:this 是访问本类实例属性或方法;super 是子类访问父类中的属性或方法。
  • 查找范围:this 先查本类,没有的话再查父类;super 直接访问父类。
  • 使用:this 单独使用时,表示当前对象;super 在子类覆盖父类方法时,访问父类同名方法。

在静态方法中可以使用 this 或 super 吗?为什么?

在静态方法中不能使用 this 或 super,因为 this 和 super 指代的都是需要被创建出来的对象,而静态方法在类加载的时候就已经创建了,所以没办法在静态方法中使用 this 或 super。

静态方法的使用需要注意哪些问题?

静态方法的使用需要注意以下两个问题:

  • 静态方法中不能使用实例成员变量和实例方法;
  • 静态方法中不能使用 this 和 super。

final 修饰符的作用有哪些?

final也是很多面试喜欢问的地方,但我觉得这个问题很无聊,通常能回答下以下5点就不错了:

  • 被final修饰的类不可以被继承
  • 被final修饰的方法不可以被重写
  • 被final修饰的变量不可以被改变.如果修饰引用,那么表示引用不可变,引用指向的内容可变.
  • 被final修饰的方法,JVM会尝试将其内联,以提高运行效率
  • 被final修饰的常量,在编译阶段会存入常量池中.

除此之外,编译器对final域要遵守的两个重排序规则更好:

在构造函数内对一个final域的写入,与随后把这个被构造对象的引用赋值给一个引用变量,这两个操作之间不能重排序 初次读一个包含final域的对象的引用,与随后初次读这个final域,这两个操作之间不能重排序.

经典使用场景:Integer,String等类中有使用到。

覆盖 equals() 方法的时候需要遵守哪些规则?

Oracle 官方的文档对于 equals() 重写制定的规则如下。

  • 自反性:对于任意非空的引用值 x,x.equals(x) 返回值为真。
  • 对称性:对于任意非空的引用值 x 和 y,x.equals(y) 必须和 y.equals(x) 返回相同的结果。
  • 传递性:对于任意的非空引用值 x、y 和 z,如果 x.equals(y) 返回值为真,y.equals(z) 返回值也为真,那么 x.equals(z) 也必须返回值为真。
  • 一致性:对于任意非空的引用值 x 和 y,无论调用 x.equals(y) 多少次,都要返回相同的结果。在比较的过程中,对象中的数据不能被修改。
  • 对于任意的非空引用值 x,x.equals(null) 必须返回假。

此题目不要求记忆,能知道大概即可,属于加分项题目。

在 Object 中 notify() 和 notifyAll() 方法有什么区别?

notify() 方法随机唤醒一个等待的线程,而 notifyAll() 方法将唤醒所有在等待的线程。

如何使用 clone() 方法?

如果是同一个类中使用的话,只需要实现 Cloneable 接口,定义或者处理 CloneNotSupportedException 异常即可,请参考以下代码:

public class CloneTest implements Cloneable {
    int num;
    public static void main(String[] args) throws CloneNotSupportedException {
        CloneTest ct = new CloneTest();
        ct.num = 666;
        System.out.println(ct.num);
        CloneTest ct2 = (CloneTest) ct.clone();
        System.out.println(ct2.num);
    }
}

如果非内部类调用 clone() 的话,需要重写 clone() 方法,请参考以下代码:

class CloneTest implements Cloneable {
    int num;
    public static void main(String[] args) throws CloneNotSupportedException {
        CloneTest ct = new CloneTest();
        ct.num = 666;
        System.out.println(ct.num);
        CloneTest ct2 = (CloneTest) ct.clone();
        System.out.println(ct2.num);
    }
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}
public class CloneTest2 {
    public static void main(String[] args) throws CloneNotSupportedException {
        CloneTest ct = new CloneTest();
        ct.num = 666;
        System.out.println(ct.num);
        CloneTest ct2 = (CloneTest) ct.clone();
        System.out.println(ct2.num);
    }
}

对象克隆是原型模式的经典实现。

java中对象的创建方式有哪几种?

java中提供了以下四种创建对象的方式:

  • new创建新对象
  • 通过反射机制
  • 采用clone机制
  • 通过序列化机制

总结

本文讲述的是一些基本的java入门知识,也顺带着讲了些稍微有点挑战的,对于还是小白的同学,有些东西不懂没事,先混个眼熟,多见几次面后,就会慢慢熟悉了,如果有机会在深入的领悟一番,那不懂的也就懂了。

每天保持学习的心态,一个月后,一年后,如果你觉得再回看之前的你,如果觉得自己当初很傻逼,那证明你进不了,如果和之前没什么两样,那证明你还是没有进步,需要反思了。


标签:面试题,java,构造方法,附带,子类,System,父类,public,out
From: https://blog.51cto.com/u_11702014/6443924

相关文章

  • 写给小白看的线程池,还有10道面试题
    为什么要用线程池呢?下面是一段创建线程并运行的代码:for(inti=0;i<100;i++){newThread(()->{System.out.println("runthread->"+Thread.currentThread().getName());userService.updateUser(....);}).start();}我们想使用这种方式去做......
  • 如何吃透一个Java项目?
    现在Austin的文档我觉得还是比较全的,但到了看代码的时候,可能有的同学就不知道应该怎么看,有想知道模块之间的调用链路,有想一点一点把细节给全看了。这时候就很可能在项目里犯迷糊了,绕不出不来了。Java开源项目消息推送平台......
  • Java 的 8 种异步实现方式
    异步的八种实现方式线程ThreadFuture异步框架CompletableFutureSpring注解@AsyncSpringApplicationEvent事件消息队列第三方异步框架,比如Hutool的ThreadUtilGuava异步1.线程异步public class AsyncThread extends Thread {    @Override    public vo......
  • Java反射机制详解上篇
    1反射机制是什么反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。在面向对象的世界里,万事万物皆对象.在java语言里,静态的成员,普......
  • Java多态综合案例(包含接口,接口实现类)
    首先定义一个接口名为USB其次定义两个实现类分别名为KeyBorad和Mouse此时就可以使用多态了,因为实现类和接口某种意义上来说是继承关系。USBu=newKeyborad();USBu2 =newMouse();因为键盘和鼠标都具有插拔功能,所以为了方便,把这两个功能写入接口,然后实现类重写。pac......
  • 一个Java对象到底占用多大内存?
    一个Java对象到底占用多大内存? 最近在读《深入理解Java虚拟机》,对Java对象的内存布局有了进一步的认识,于是脑子里自然而然就有一个很普通的问题,就是一个Java对象到底占用多大内存?在网上搜到了一篇博客讲的非常好:http://yueyemaitian.iteye.com/blog/2033046,里面提供的......
  • java分页代码
    现在开始编写 Service 层代码:在 com.game.products.services.iface 包中新建 ProductsService 接口,代码如下:packagecom.game.products.services.iface;importjava.util.List;importcom.game.products.model.Products;publicint......
  • javascript操作xml(增删改查)例子代码
    关键字:javascript操作xml(增删改查)自己做了一个小东西,不是很好,但是对初学来说是一个不错的例子!包括了stu.hta(是HTML应用程序);stu.xml注意下面的HTML代码必须保存为后缀名为hta否则当对XML文件进行操作(增删改)的时候就会提示没有权限!!文件stu.hta代码如......
  • javaScript通用数据类型校验_2
    /*要求:一、电话号码由数字、"("、")"和"-"构成二、电话号码为3到8位三、如果电话号码中包含有区号,那么区号为三位或四位四、区号用"("、")"或"-"和其他部分隔开用途:检查输入的电话号码格式是否正确输入:strPhone:字符串返回:如果通过验证返回true,否......
  • Java拓展-拆,装箱,线程,反射
    导言:在学习JavaSE的时候,我们会使用Java基础编程,并且了解了什么是面向对象的编程,会使用Java写一些基础算法程序,接下来,我们需要了解Java的自动拆箱和自动装箱,单线程和多线程,反射是什么,值得注意的是,讲的是Java中的特性,但是OOP语言其实都是用这些操作的,只是小部分不同罢了一.自动拆......