JAVA 学习 面试 (一) 基础预热篇

发布时间:2024年01月22日
  • 面向过程:就是具体化的一步一步的去实现,优点 就是性能比较快因为不需要进行实例化。 缺点就是不容易进行维护,扩展和复用
  • 面向对象:因为面向对象的三大特点就是 封装、继承和多态
面向对象(OOP)

img

3.1、封装

定义:使用对象封装一些变量和函数

作用:复用和信息隐藏,封装,也就是把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏。

3.2、抽象

抽象就是找出一些事物的相似和共性之处,然后将这些事物归为一个类,这个类只考虑这些事物的相似和共性之处,并且会忽略与当前主题和目标无关的那些方面,将注意力集中在与当前目标有关的方面。例如,看到一只蚂蚁和大象,你能够想象出它们的相同之处,那就是抽象。抽象包括行为抽象和状态抽象两个方面。

3.3、继承

定义:一个类获取另外一个类属性和方法的一种方式

作用:代码复用,继承,就是可以使用已创建好的类的所有功能,并在无需重新编写原来的类的情况下对这些功能进行扩展。

3.4、多态

定义:同一个操作,作用于不用的对象,会有不同的行为

作用:具有可拓展性详解:多态首先是建立在继承的基础上的,先有继承才能有多态。多态是指不同的子类在继承父类后分别都重写覆盖了父类的方法,即父类同一个方法,在继承的子类中表现出不同的形式。js天生就具备多态的特性(弱类型语言)

原理:靠的是父类或接口定义的引用变量可以指向子类或具体实现类的实例对象,而程序调用的方法在运行期才动态绑定

## AOP和OOP
OOP主要功能封装、继承、多态,AOP它是将系统分解为不同的关注点(不同的切面)。

OOP,我们会根据业务将应用划分为多个不同的业务模块,每个模块的核心功能只为某个核心业务提供服务,如学生宿舍管理系统,学生管理、班级管理、房间管理,分别学生、班级、房间服务的。
除此之外,还会有一些非业务的通用功能,如日志、权限、事务管理等。它们和业务无关,但是几乎所有的模块都会用到它。因此这些通用功能会散布在不同的业务模块中。此时会有很多重复性的代码,不理模块的复用。
为了解决这个问题,AOP(面向切面编程)就出来了,它是把非业务的通用功能抽取出来单独维护,并通过声明的方式(定义切入点)去指定这些功能以何种方式(通知类型)作用在哪里(方法连接点--目标方法),而不是直接在模块的代码中去直接添加。
数据类型

img

基本数据类型

在这里插入图片描述

为什么float=3.4报错

3.4 默认是浮点double类型的,如果赋值给float是向下转型,会出现精度缺失,,需要强制转换

Switch支持的数据类型?

byte、short、int、char 、 enum 、 String

基本类型与包装类的区别
## 存储位置不同:
基本数据类型直接将值放在栈中;(非static的成员变量存在堆中)
包装类型是把对象放在堆中,然后通过对象的引用来调用他们 ;
## 初始值不同:
int的初始值为 0 、 boolean的初始值为false ;
包装类型的初始值为null ;
## 使用方式不同:
基本数据类型直接赋值使用就好;
在集合如 coolectionMap 中只能使用包装类型;包装类型可以使用在泛型中
基本类型与包装类的相互转换
## 手动转换
基本数据类型 → 包装类:
    通过对应包装类的构造方法实现(Integer.valueOf(10)),除了Character外,其他包装类都可以传入一个字符串参数构建包装类对象。
包装类 → 基本数据类型
    通过包装类的实例方法 xxxValue() 实现; // xxx表示包装类对应的基本数据类型
## 自动装箱&自动拆箱(jdk1.5以后)
基本类型添加到集合中时,进行自动装箱
包装类型在涉及到运算的时候,“加,减,乘, 除” 以及 “比较 equals,compareTo”,进行自动拆箱
包装类型的缓存机制

Byte,Short,Integer,Long 这 4 种包装类默认创建了数值 [-128,127] 的相应类型的缓存数据,Character 创建了数值在 [0,127] 范围的缓存数据,Boolean 直接返回 True or False

Integer i1 = 33;
Integer i2 = 33;
System.out.println(i1 == i2);// 输出 true

Integer i1 = 40;
Integer i2 = new Integer(40);
System.out.println(i1==i2); // 输出 False

引用数据类型 和 数组

## 引用数据类型的变量定义及赋值格式:
数据类型 变量名 = new 数据类型();
调用该类型实例的功能:变量名.方法名();
## 数组
一组数据的集合,数组中的每个数据被称作'元素'
在数组中可以存放'任意类型'的元素但'同一个数组'里存放的元素类型必须一致。
格式: int[] x = new int[100];
使用属性:数组名.length
方法

构成:

  • 访问修饰符:方法允许被访问的权限范围。( public,protected,private,无修饰符 )
  • 参数列表:可以省略。参数类型 + 参数名,…
  • 返回类型:void、任何数据类型

注意:

  • 方法参数是 基本类型 ,传递的是值。(包含String类型),形式参数的改变对实际参数不影响
  • 方法参数是 引用类型,传递的是内存地址值。(String类型除外),形式参数的改变对实际参数有影响

可变参数:

public void sum(int... n){}
  • 可变参数一定在最后,可以将数组传递给可变参数列表
  • 可变参数的实质就是数组:一个参数是可变参数,一个参数是一维数组,这两个方法不是重载,因为 一个可变参数等价于相应类型的一维数组
  • 方法重载的时候,既可以定义有可变参数的同名方法,也可以定义有确定参数个数的方法,jvm调用方法时,会优先调用 有确定参数个数 的方法
设计模式
## 1、创建型模式
对象实例化的模式,创建型模式用于解耦对象的实例化过程。
单例模式:某个类智能有一个实例,提供一个全局的访问点。
工厂模式:一个工厂类根据传入的参量决定创建出哪一种产品类的实例。
抽象工厂模式:创建相关或依赖对象的家族,而无需明确指定具体类。
建造者模式:封装一个复杂对象的创建过程,并可以按步骤构造。
原型模式:通过复制现有的实例来创建新的实例。

## 2、结构型模式
把类或对象结合在一起形成一个更大的结构。
装饰器模式:动态的给对象添加新的功能。
代理模式:为其它对象提供一个代理以便控制这个对象的访问。
桥接模式:将抽象部分和它的实现部分分离,使它们都可以独立的变化。
适配器模式:将一个类的方法接口转换成客户希望的另一个接口。
组合模式:将对象组合成树形结构以表示“部分-整体”的层次结构。
外观模式:对外提供一个统一的方法,来访问子系统中的一群接口。
享元模式:通过共享技术来有效的支持大量细粒度的对象。

## 3、行为型模式
类和对象如何交互,及划分责任和算法。
策略模式:定义一系列算法,把他们封装起来,并且使它们可以相互替换。
模板模式:定义一个算法结构,而将一些步骤延迟到子类实现。
命令模式:将命令请求封装为一个对象,使得可以用不同的请求来进行参数化。
迭代器模式:一种遍历访问聚合对象中各个元素的方法,不暴露该对象的内部结构。
观察者模式:对象间的一对多的依赖关系。
仲裁者模式:用一个中介对象来封装一系列的对象交互。
备忘录模式:在不破坏封装的前提下,保持对象的内部状态。
解释器模式:给定一个语言,定义它的文法的一种表示,并定义一个解释器。
状态模式:允许一个对象在其对象内部状态改变时改变它的行为。
责任链模式:将请求的发送者和接收者解耦,使的多个对象都有处理这个请求的机会。
访问者模式:不改变数据结构的前提下,增加作用于一组对象元素的新功能。

设计模式是一组重复的经验,大多数人都知道,编目和代码设计经验。使用设计模式是重用代码,使代码更容易被其他人理解,并确保代码的可靠性。

单例模式

单例模式就是在程序运行中只实例化一次,创建一个全局唯一对象。

饿汉模式:不能实现懒加载,造成空间浪费

//在类加载时就完成了初始化,所以类加载较慢,但获取对象的速度快
public class SingletonObject {
    // 利用静态变量来存储唯一实例
    private static final SingletonObject instance = new SingletonObject();
 
    // 私有化构造函数
    private SingletonObject(){
        // 里面可能有很多操作
    }
 
    // 提供公开获取实例接口
    public static SingletonObject getInstance(){
        return instance;
    }
}

懒汉模式:

  • 在不加锁的情况下,线程不安全,可能出现多份实例
  • 在加锁的情况下,会是程序串行化,使系统有严重的性能问题
public class SingletonObject {
    // 定义静态变量时,未初始化实例
    private static SingletonObject instance;
 
    // 私有化构造函数
    private SingletonObject(){
 
    }
 
    public static SingletonObject getInstance(){
        // 使用时,先判断实例是否为空,如果实例为空,则实例化对象
        // 这段代码在多线程的情况下是不安全的
        if (instance == null)
            instance = new SingletonObject();
        return instance;
    }
}

静态内部类单例模式:静态内部类单例模式实例由内部类创建,由于 JVM 在加载外部类的过程中, 是不会加载静态内部类的, 只有内部类的属性/方法被调用时才会被加载, 并初始化其静态属性。

public class SingletonObject {
    private SingletonObject(){
 
    }
    // 单例持有者
    private static class InstanceHolder{
        private  final static SingletonObject instance = new SingletonObject();
    }
    // 
    public static SingletonObject getInstance(){
        // 调用内部类属性
        return InstanceHolder.instance;
    }
}

枚举类单例模式:枚举类型是线程安全的,并且只会装载一次,而且枚举类型是所用单例实现中唯一一种不会被破坏的单例实现模式。

public class SingletonObject {
    private SingletonObject(){
 
    }
    private enum Singleton{
        INSTANCE;
        private final SingletonObject instance;
 
        Singleton(){
            instance = new SingletonObject();
        }
 
        private SingletonObject getInstance(){
            return instance;
        }
    }
    public static SingletonObject getInstance(){
        return Singleton.INSTANCE.getInstance();
    }
}

除枚举方式外,其他方法都会通过反射的方式破坏单例,反射是通过调用构造方法生成新的对象,所以如果我们想要阻止单例破坏,可以在构造方法中进行判断,若已有实例, 则阻止生成新的实例。

private SingletonObject(){
    if (instance !=null){
        throw new RuntimeException("实例已经存在,请通过 getInstance()方法获取");
    }
}

如果单例类实现了序列化接口Serializable, 就可以通过反序列化破坏单例,所以我们可以不实现序列化接口,如果非得实现序列化接口,可以重写反序列化方法readResolve(), 反序列化时直接返回相关单例对象。

public Object readResolve() throws ObjectStreamException {
    return instance;
}
工厂模式
  • 简单工厂模式:一个工厂对象决定创建哪一种产品类型的实例,只适用于工厂类负责创建的对象较少的场景
  • 工厂方法模式:定义一个创建对象的接口,但让实现这个接口的类来决定实例化哪个类。工厂方法让类的实例化推迟到子类中进行
抽象工厂模式
  • 抽象工厂模式建议为系列中的每件产品明确声明接口(例如椅子、沙发或咖啡桌)。然后,确保所有产品变体都继承这些接口。例如,所有风格的椅子都实现椅子接口;所有风格的咖啡桌都实现咖啡桌接口,以此类推。
  • 接下来,我们需要声明抽象工厂——包含系列中所有产品构造方法的接口。例如create-Chair创建椅子、create-Sofa创建沙发和create-Coffee-Table创建咖啡桌。这些方法必须返回抽象产品类型,即我们之前抽取的那些接口:椅子,沙发和咖啡桌等等。
  • 我们都将基于抽象工厂接口创建不同的工厂类。每个工厂类都只能返回特定类别的产品,例如,现代家具工厂 Modern-Furniture-Factory 只能创建现代椅子 Modern-Chair 、现代沙发 Modern-Sofa 和现代咖啡桌Modern-Coffee-Table 对象。
  • 客户端代码可以通过相应的抽象接口调用工厂和产品类。你无需修改实际客户端代码,就能更改传递给客户端的工厂类,也能更改客户端代码接收的产品变体。
  • 最后一点说明:如果客户端仅接触抽象接口,那么谁来创建实际的工厂对象呢?一般情况下, 应用程序会在初始化阶段创建具体工厂对象。而在此之前,应用程序必须根据配置文件或环境设定选择工厂类别。
抽象产品(Abstract Product)为构成系列产品的一组不同但相关的产品声明接口。
具体产品(Concrete Product)是抽象产品的多种不同类型实现。所有变体(维多利亚/现代)都必须实现相应的抽象产品(椅子/沙发)。
抽象工厂(Abstract Factory)接口声明了一组创建各种抽象产品的方法。
具体工厂(Concrete Factory)实现抽象工厂的构建方法。每个具体工厂都对应特定产品变体,且仅创建此种产品变体。
装饰器模式

装饰器(Decorator)模式的定义:指在不改变现有对象结构的情况下,动态地给该对象增加一些职责(即增加其额外功能)的模式,它属于对象结构型模式。

装饰器模式的主要优点有:

  • 装饰器是继承的有力补充,比继承灵活,在不改变原有对象的情况下,动态的给一个对象扩展功能,即插即用
  • 通过使用不用装饰类及这些装饰类的排列组合,可以实现不同效果
  • 装饰器模式完全遵守开闭原则
package decorator;
import java.awt.*;
import javax.swing.*;
public class MorriganAensland {
    public static void main(String[] args) {
        Morrigan m0 = new original();
        m0.display();
        Morrigan m1 = new Succubus(m0);
        m1.display();
        Morrigan m2 = new Girl(m0);
        m2.display();
    }
}
//抽象构件角色:莫莉卡
interface Morrigan {
    public void display();
}
//具体构件角色:原身
class original extends JFrame implements Morrigan {
    private static final long serialVersionUID = 1L;
    private String t = "Morrigan0.jpg";
    public original() {
        super("《恶魔战士》中的莫莉卡·安斯兰");
    }
    public void setImage(String t) {
        this.t = t;
    }
    public void display() {
        this.setLayout(new FlowLayout());
        JLabel l1 = new JLabel(new ImageIcon("src/decorator/" + t));
        this.add(l1);
        this.pack();
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setVisible(true);
    }
}
//抽象装饰角色:变形
class Changer implements Morrigan {
    Morrigan m;
    public Changer(Morrigan m) {
        this.m = m;
    }
    public void display() {
        m.display();
    }
}
//具体装饰角色:女妖
class Succubus extends Changer {
    public Succubus(Morrigan m) {
        super(m);
    }
    public void display() {
        setChanger();
        super.display();
    }
    public void setChanger() {
        ((original) super.m).setImage("Morrigan1.jpg");
    }
}
//具体装饰角色:少女
class Girl extends Changer {
    public Girl(Morrigan m) {
        super(m);
    }
    public void display() {
        setChanger();
        super.display();
    }
    public void setChanger() {
        ((original) super.m).setImage("Morrigan2.jpg");
    }
}

动图

桥接模式
  • 定义:就是把抽象和实现分离出来,然后中间通过组合来搭建他们之间的桥梁。
  • 业务场景:中国有很多银行,有中国农业银行和中国工商银行;关于我们的账号,有定期账号和活期账号,一个就是银行一个就是我们的账号。
代理模式

代理模式是一种设计模式,提供了对目标对象额外的访问方式,即通过代理对象访问目标对象,这样可以在不修改原目标对象的前提下,提供额外的功能操作,扩展目标对象的功能。

静态代理:在编译时就已经实现,编译完成后代理类是一个实际的class文件。

创建一个接口,然后创建被代理的类实现该接口并且实现该接口中的抽象方法。之后再创建一个代理类,同时使其也实现这个接口。在代理类中持有一个被代理对象的引用,而后在代理类方法中调用该对象的方法。

动态代理:通过Proxy.getProxyClass获得动态代理类;

通过反射机制获得代理类的构造方法,方法签名为getConstructor(InvocationHandler.class)

通过构造函数获得代理对象并将自定义的InvocationHandler实例对象传为参数传入;

适配器模式

类适配器:Adapter 类,通过继承 src 类,实现 dst 类接口,完成 src->dst 的适配。

 // src
public class Voltage220V{
    public int output220V() {
        int src = 220;
        System.out.println("电压:" + src);
        return src;
    }
}
// dst
public interface IVoltage5V {
    int output5V();
}
// adapter
public class VoltageAdapter extends Voltage220V implements IVoltage5V{
    @Override
    public int output5V() {
        int srcV = output220V();
        int dstV = srcV / 44;
        return dstV;
    }  
}
//使用
public class Client {

    public static void main(String[] args) {
        System.out.println("适配器模式");
        Phone phone = new Phone();
        phone.charging(new VoltageAdapter());
    }
}
  1. Java 是单继承机制,所以类适配器需要继承 src 类这一点算是一个缺点, 因为这要求 dst 必须是接口,有一定局限性;

  2. src 类的方法在 Adapter 中都会暴露出来,也增加了使用的成本。

对象适配器:基本思路和类的适配器模式相同,只是将 Adapter 类作修改,不是继承 src 类,而是持有 src 类的实例,以解决兼容性的问题。 即:持有 src 类,实现 dst 类接口,完成 src->dst 的适配

public class Client {
    public static void main(String[] args) {
        System.out.println("适配器模式");
        Phone phone = new Phone();
        phone.charging(new VoltageAdapter(new Voltage220V()));
    }
}
观察者模式

观察者模式是一种行为设计模式,指多个对象间存在一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。 这种模式和发布-订阅模式很像,不同的是,发布-订阅模式,一般有一个调度中心,调度中心有拉模式和推模式来推送消息。

//抽象观察者
public interface Observer {
 void response(); //反应
}
public class ConcreteStudentA implements Observer{
 @Override
 public void response() {
  System.out.println("学生A,收起自己的零食");
 }
}
//抽象主题,提供保存观察者的类,可以新增或移除观察者
public abstract class Subject {
  protected List<Observer> observers = new ArrayList<Observer>();
 //增加观察者方法
    public void add(Observer observer) {
        observers.add(observer);
    }
    //删除观察者方法
    public void remove(Observer observer) {
        observers.remove(observer);
    }
    public abstract void notifyObserver(); //通知观察者方法
}
//具体主题
public class ConcreteSubject extends Subject{

 @Override
 public void notifyObserver() {
  System.out.println("被观察者看到班主任来了,喊了一句:老师来了!");
  for (Object obs : observers) {
   ((Observer)obs).response(); //观察者做出反应
  }
 }
}
策略模式

对象有某个行为,但是在不同的场景中,该行为有不同的实现算法.。比如每个人都要“交个人所得税”,但是“在美国交个人所得税”和“在中国交个人所得税”就有不同的算税方法.定义一组算法,将每个算法都封装起来,并且使它们之间可以互换。

思想:在运行时(非编译时)改变软件的算法行为,定义一个通用的问题,使用不同的算法来实现,然后将这些算法都封装在一个统一接口。

Strategy bySubway = new BySubwayStrategy();
//乘地铁
Context ctx = new Context(bySubway);
ctx.goToPark();
//乘公交
Strategy byBus = new ByBusStrategy();
ctx.setStrategy(byBus);
ctx.goToPark();

应用:当有大量条件语句在同一算法的不同变体之间切换时,可将每个条件分支移入它们各自的策略类中替代这些条件语句,来消除这种条件。

责任链模式

在面向对象的开发中,往往力求对象之间保持松耦合,确保对象各自的责任最小化、具体化。经常用Filter做拦截器,即把所有的Filter都放在FilterChain中,然后依次执行每个过滤器,有符合条件的就处理,直到没有其他过滤器,就访问请求的资源。

public interface LeaderChain {
 public abstract void setNextChain(LeaderChain nextChain);
 public abstract void handleRequest(int days);
}
//组长
public class GroupLeader implements LeaderChain{
 private LeaderChain nextChain;
    //这部分可以提取BaseHandle
 @Override
 public void setNextChain(LeaderChain nextChain) {
  this.nextChain=nextChain;
 }

 @Override
 public void handleRequest(int days) {
  if(1==days){
   System.out.println("组长同意");
  }else{
   //交给上一级处理
   this.nextChain.handleRequest(days);
  }
 }
}
//...部门经理,部门总监,总经理
public static void Leaveapplication(int days){
  LeaderChain gl = new GroupLeader();
  LeaderChain dp = new DpManager();
  LeaderChain cf = new CfInspector();
  LeaderChain gm = new GeneralManager();
  gl.setNextChain(dp);
  dp.setNextChain(cf);
  cf.setNextChain(gm);
  //提交请求
  gl.handleRequest(days);
 }
}
备忘录模式

? 备忘录模式是一种行为设计模式,又叫快照模式,是指在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,以便以后需要时能将该对象恢复到原先保存的状态。具体采用哪种方法来存储对象状态,取决于对象需要保存时间的长短。

  • ? 1)发起人(Originator)角色:记录当前时刻的内部状态,负责定义哪些属于备份范围的状态,负责创建和恢复备忘录数据,它可以访问备忘录里所有的信息;
  • ? 2)备忘录(Memento)角色:负责存储发起人的内部状态,在需要的时候提供这些内部状态给发起人;
  • ? 3)管理者(Caretaker)角色:对备忘录进行管理、保存和提供备忘录,但其不能对备忘录的内容进行访问与修改。
public class LolOriginator {  // 发起者
  public LolOriginator(String name,String type,Integer fightingNum){
    this.name = name;
    this.type = type;
    this.fightingNum = fightingNum;
   }

   //创建一个备忘录,进行备忘操作
   public LolMemento createMemento(){
    return new LolMemento(this);
   }

   //恢复成指定备忘录
   public void restoreMemento(LolMemento memento){
    this.name = memento.getName();
    this.type = memento.getType();
    this.fightingNum = memento.getFightingNum();
   }
 }
//备忘录
public class LolMemento {

 private String name; //英雄名字
 private String type; //英雄类型
 private Integer  fightingNum; //英雄战斗力
 
 public LolMemento(LolOriginator lol){
  this.name=lol.getName();
  this.type=lol.getType();
  this.fightingNum = lol.getFightingNum();
 }
}
//管理者,负责管理备忘录对象
public class LolCaretaker {
 private LolMemento memento;
 //如果有一连串的状态加成,可以保存多个状态
 //private List<LolMemento> mementoList = new ArrayList<LolMemento>();
 public LolMemento getMemento() {
  return memento;
 }
 public void setMemento(LolMemento memento) {
  this.memento = memento;
 }
}
//使用
 public static void main(String[] args) {
  //备忘录管理者
  LolCaretaker taker = new LolCaretaker();
  //创建一个英雄
  System.out.println("当前的英雄信息:");
  LolOriginator lol = new LolOriginator("德玛西亚之力", "战士", 666);
  System.out.println("  "+lol.toString());
  //进行一次备忘
  taker.setMemento(lol.createMemento());

  System.out.println("吃了一个红buff:");
  lol.setFightingNum(700);
  System.out.println("  "+lol.toString());
  
  System.out.println("红buff已经失效:");
  lol.restoreMemento(taker.getMemento());  //恢复到之前的状态
 }
}
文章来源:https://blog.csdn.net/qq_42767993/article/details/135683759
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。