• 自动化之Java面试


    1.重写与重载的区别

    重载规则:
    重载是指在同一个类中,定义了多个同名方法,但同名方法的参数类型或参数个数不同就是方法重载,节约词汇,例如driver.switchTo().frame(index/nameOrId/frameElement),方法重载的经典使用场景是 String 类型的 valueOf 方法,valueOf 方法重载有 9 种实现
    java的重载(overload) 最重要的应用场景就是构造器的重载,目的是对方法(构造器)进行功能扩展,以应对多业务场景的不同使用需求。提高程序的健壮性和扩展性

    重写规则:
    建立在继承关系上,子类和父类的方法名称,参数类型、参数个数全部相同,不仅可以得到父类的东西,同时也加入了自己的东西,重用性,扩展性,复用性,用@override关键字修饰,比较经典的是 Object 类中的 equals 方法。 Object 是所有类的父类
    简单总结:
    总结
    方法重写(Override)和方法重载(Overload)都是面向对象编程中,多态特性的不同体现,方法重写描述的是父类和子类的方法关系,而方法重载描述的是同一个类中多个同名方法的方法关系。除此之外方法重写和方法重载还有:Override 关键字、参数类型和参数个数、返回类型、抛出异常和权限控制符等不同点。
    生活例子:
    你想吃一碗面,我给你提供了拉面,炒面,刀削面,担担面供你选择,这是重载;
    你想吃一碗面,我不但给你端来了面,还给你加了青菜,加了鸡蛋,这个是重写;
    方法的重载和重写都是实现多态的方式,区别在于前者实现的是编译时的多态性,而后者实现的是运行时的多态性。

    2.==“和equals方法究竟有什么区别

    "和equals方法究竟有什么区别?
    ==:用于基本类型数据的比较,比较的是值
    用于引用数据类型的比较所指向的对象的地址
    equals:不能用于基本类型的数据的比较
    用于引用类型的比较:
    如果没有对equals进行重写,比较的是引用类型的变量所指向的对象的地址
    如果对equals进行重写,比较的是所指向的对象的内容(String/Date)又可分为两种情况:
    hashcode进行重写:
    如果相同,equals()方法返回值不能确定,可能为true,也可能为false
    不相同,用equals()方法判断返回的一定是false
    不对hashcode进行重写,用equals()方法判断返回的一定是true

    3.static的基本用法

    static:表示“全局”或“静态”的意思,修饰类的成员方法和成员变量,也可以编写static代码块优化程序性能

    a.static修饰的成员方法
    一般称为“静态方法”,它不依赖于任何对象就能进行访问,可以使用“ 类名.方法名”的方式操作方法,避免了先要new出对象的
    繁琐和资源消耗,它也没有this和super关键字,静态方法中不能访问非静态成员变量和非静态成员方法,因为非静态成员变量和
    非静态成员方法必须依赖具体的对象才能够被调用,但是对于非静态成员方法是可以访问静态成员方法和静态变量的。
    b.static修饰的变量
    一般称为“静态变量”或“类变量”,静态变量与非静态变量的区别是:静态变量所在的类的所有对象共享这一个属性(不同的类中不共享),
    在内存中只有一个副本,它当且仅当在类初始加载时才会被初始化,非静态变量是对象所拥有的,在创建对象时被初始化,存在多个副本,
    各个对象拥有的副本相互不影响,可以用“类名.静态变量”或“对象.静态变量”进行访问,但“类名.静态变量”更能体现出static的作用。
    局部变量不能声明为静态变量。static变量进行初始化时有默认值,final static初始化时必须有初始值
    以下两种情况使用static变量:(1)静态变量所在的类的所有对象直接共享数据(2)访问变量时
    c.static代码块
    一般称为“静态代码块”,可放在类中的任何地方,类中可有多个static代码块,在类初次被加载时会按照static代码块顺序来执行每个static
    代码块并且只会执行一次,静态代码块不能放在任何方法的内部

    **总结:**static的基本作用:方便在没有创建对象情况下调用方法/变量

    4.接口和抽象类的区别

    接口是对行为的抽象,接口是公开的,不能有私有的方法或变量,接口中的所有方法都没有方法体,通过关键字interface实现
    特点:
    接口中可以含有变量和方法。但是要注意,接口中的变量会被隐式地指定为public static final变量(并且只能是public static final变量,用private修饰会报编译错误),而方法会被隐式地指定为public abstract方法且只能是public abstract方法(用其他关键字,比如private、protected、static、 final等修饰会报编译错误),并且接口中所有的方法不能有具体的实现,也就是说,接口中的方法必须都是抽象方法。
    从这里可以隐约看出接口和抽象类的区别,接口是一种极度抽象的类型,它比抽象类更加“抽象”,并且一般情况下不在接口中定义变量。
    如果一个非抽象类遵循了某个接口,就必须实现该接口中的所有方法。对于遵循某个接口的抽象类,可以不实现该接口中的抽象方法。

    抽象类就是为了继承而存在的,如果你定义了一个抽象类,却不去继承它,那么等于白白创建了这个抽象类,因为你不能用它来做任何事情。对于一个父类,如果它的某个方法在父类中没有任何意义,必须根据子类的实际需求来进行
    特点:
    abstract修饰的类为抽象类,此类不能有对象,(无法对此类进行实例化); abstract修饰的方法为抽象方法,是抽象方法,此方法不能有方法体(为空),包含抽象方法的类称为抽象类,但并不意味着抽象类中只能有抽象方法,如果一个类继承于一个抽象类,则子类必须实现父类的抽象方法。如果子类没有实现父类的抽象方法,则必须将子类也定义为为abstract类。

    在接口和抽象类的选择上,必须遵守这样一个原则:
    行为模型应该总是通过接口而不是抽象类定义,所以通常是优先选用接口,尽量少用抽象类。
    选择抽象类的时候通常是如下情况:需要定义子类的行为,又要为子类提供通用的功能

    5.深拷贝和浅拷贝的区别是什么?

    浅拷贝:被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象.换言之,浅拷贝仅仅复制所考虑的对象,而不复制它所引用的对象

    深拷贝:被复制对象的所有变量都含有与原来的对象相同的值.而那些引用其他对象的变量将指向被复制过的新对象.而不再是原有的那些被引用的对象.换言之.深拷贝把要复制的对象所引用的对象都复制了一遍.

    6.文件读取

    FileInputstream / FileOutputstream
    FileReader / FileWriter

    7.List,Set,Map三者的区别

    List(对付顺序的好帮手): List接口存储一组不唯一(可以有多个元素引用相同的对象),有序
    的对象
    Set(注重独一无二的性质): 不允许重复的集合。不会有多个元素引用相同的对象。
    Map(用Key来搜索的专家): 使用键值对存储。Map会维护与Key有关联的值。两个Key可以引用相同的对象,但Key不能重复,典型的Key是String类型,但也可以是任何对象

    8.创建对象有几种方式

    new、反射、clone 拷贝、反序列化。

    9.String、String StringBuffer 和 StringBuilder 的区别是什么

    String是只读字符串,它并不是基本数据类型,而是一个对象。从底层源码来看是一个final类型的字符数组,所引用的字符串不能被改变,一经定义,无法再增删改。每次对String的操作都会生成新的String对象。
    StringBuffer和StringBuilder他们两都继承了AbstractStringBuilder抽象类,从AbstractStringBuilder抽象类中我们可以看到, 他们的底层都是可变的字符数组,所以在进行频繁的字符串操作时,建议使用StringBuffer和StringBuilder来进行操作。 另外StringBuffer 对方法加了同步锁或者对调用的方法加了同步锁,所以是线程安全的。StringBuilder 并没有对方法进行加同步锁,所以是非线程安全的。

    10.反射的基础应用

    概述:反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能调用它的任意一个属性和方法,这种能够动态获取信息以及动态调用对象的方法的功能称为Java的反射机制。
    要想解剖一个类,必须先要获取到该类的字节码文件对象,而解剖使用的就是Class类中的方法,所以先要获得
    每一个字节码文件对应的Class类型的对象。反射就是把Java类中的各种成分映射成一个个的Java对象
    一.Class类:代表一个类
    Field类:代表类的成员变量(类的属性)
    Method类:代表类的方法
    Construtor类:代表类的构造方法
    Arrary类:提供了动态创建数组以及访问数组的元素的静态方法
    要想操作反射,必须先拿到反射的入口
    获取Class对象的三种方式
    * 1 Object ——> getClass();//对象都有了还要反射干什么
    * 2 任何数据类型(包括基本数据类型)都有一个“静态”的class属性//需要导入类的包,依赖太强,不导包就抛编译错误
    * 3 通过Class类的静态方法:forName(String className)(常用)//,一个字符串可以传入也可写在配置文件中等多种方法
    二.通过Class对象获取类中的获取单个的"公有的"构造方法
    1、public Constructor getConstructor(Class… parameterTypes):获取单个的"公有的"构造方法
    parameterTypes:构造方法中的形参类型,例如String.class
    2.调用构造方法
    Constructor–>newInstance(Object… initargs)
    initargs:形参的具体值
    三.通过Class对象获取类中的“公有”的方法
    1.public Method getMethod(String name,Class… parameterTypes):
    name : 方法名;
    Class … : 形参的Class类型对象
    举例:
    //获取公有的构造方法
    Constructor con = clazz.getConstructor(String.class);
    con.newInstance(“曹心情构造方法”);
    2.调用方法
    Method --> public Object invoke(Object obj,Object… args)
    obj : 要调用方法的对象;
    args:调用方式时所传递的实参;
    注意:要调用方法的对象obj需要用到构造方法,实例化一个对象
    Object obj = clazz.getConstructor().newInstance();
    另外如果方法是静态的,obj可以省略,直接写null
    举例:
    //获取公有的setName()方法
    Method m = clazz.getMethod(“setName”, String.class);
    Object obj = clazz.getConstructor().newInstance();
    m2.invoke(obj, “曹普通方法”);

    11.fastjson基本使用

    一.Json格式
    1.1 JSON对象:
    {
    “name”: “张三”,
    “age”: 24
    }
    1:数据在花括号中
    2:数据以"键:值"对的形式出现(其中键多以字符串形式出现,值可取字符串,数值,甚至其他json对象)
    3:每两个"键:值"对以逗号分隔(最后一个"键:值"对省略逗号)
    1.2:JSON对象数组

    [
    {“name”: “张三”, “age”: 24},
    { “name”: “王五”, “age”: 22}
    ]
    1:数据在方括号中(可理解为数组)
    2:方括号中每个数据以json对象形式出现
    3:每两个数据以逗号分隔(最后一个无需逗号)

    1.3:两种形式的结合

    {
    “部门名称”:“研发部”,
    “部门成员”:[
    {“name”: “张三”, “age”: 24},
    {“name”: “王五”, “age”: 22}],
    “部门位置”:“xx楼21号”
    }
    1.4:JSON字符串
    1:它必须是一个字符串,由" "或者’ '包裹数据,支持字符串的各种操作
    2:里面的数据格式应该要满足其中一个格式,可以是json对象,也可以是json对象数组或者是两种基本形式的组合变形
    总结:json可以简单的分为基本形式:json对象,json对象数组。两种基本格式组合变形出其他的形式,但其本质还是json对象或者json对象数组中的一种。json对象或对象数组可以转化为json字符串,使用于不同的场合。
    注意点:在封装json数据的时候,很容易出现错误,比如粗心的在最后一条数据的末尾加上了逗号等等,这里我提供一个在线验证工具,方便大家验证json数据格式的正确性
    http://www.bejson.com/
    二:fastJson的使用
    JSONObject和JSONArray继承JSON,JSON代表JSONObject和JSONArray的转化,JSON类主要是实现转化用的,最后的数据获取,还是要通过上面的JSONObject和JSONArray来实现
    JSONObject代表json对象,底层操作是由Map实现的,通过"键:值"对中的键来获取其对应的值,通过各种形式的get()方法可以获取json对象中的数据
    JSONArray代表json对象数组,底层操作由List实现的,因为JSONArray代表json对象数组,json数组对象中存储的是一个个json对象,所以类中的方法主要用于直接操作json对象
    1.JSON类之toJSONString()方法,实现json对象转化为json字符串和javabean对象转化为json 字符串
    2.JSON类之parseObject()方法,实现json字符串转换为json对象或javabean对象:
    Student stu1=JSON.parseObject(jsonstr,Student.class);
    3.parseArray()将json字符串转化为json对象数组或转化成包含泛型的List
    三.举例使用
    public class Student {
    private String name;
    private int age;
    public String getName() {
    return name;
    }
    public void setName(String name) {
    this.name = name;
    }
    public int getAge() {
    return age;
    }
    public void setAge(int age) {
    this.age = age;
    }
    @Override
    public String toString() {
    return “Student [name=” + name + “, age=” + age + “]”;
    }
    }
    public class StudentGroup {
    private String username;
    private List stus = new ArrayList();
    public StudentGroup(){}
    public StudentGroup(String username, List stus) {
    this.username = username;
    this.stus = stus;
    }
    public String getUsername() {
    return username;
    }
    public void setUsername(String username) {
    this.username = username;
    }
    public List getStus() {
    return stus;
    }
    public void setStus(List stus) {
    this.stus = stus;
    }
    @Override
    public String toString() {
    return “StudentGroup [username=” + username + “, stus=” + stus + “]”;
    }

    }
    public class FastJson {
    public static void main(String[] args) {
    List stus = new ArrayList();
    Student student1=new Student(“bob”,24);
    Student student2=new Student(“lily”, 23);
    stus.add(student1);
    stus.add(student2);
    System.out.println(“简单java类转json字符串”);
    String str1=JSON.toJSONString(student1);
    System.out.println(str1);
    System.out.println();
    System.out.println(“List转json字符串”);
    System.out.println(JSON.toJSONString(stus));
    System.out.println();
    System.out.println(“复杂java类转json字符串”);
    StudentGroup group = new StudentGroup(“StudentGroup”, stus);
    String GroupJson = JSON.toJSONString(group);
    System.out.println(GroupJson);
    System.out.println();
    /**
    * json字符串转java对象
    * 注:字符串中使用双引号需要转义 (" --> “),这里使用的是单引号
    /
    /
    json字符串转简单java对象
    * 字符串:{“password”:“123456”,“username”:“dmego”}/
    System.out.println(“json字符串转简单java对象”);
    String jsonStr1 = “{‘name’:‘曹新晴’,‘age’:‘30’}”;
    Student student = JSON.parseObject(jsonStr1, Student.class);
    System.out.println(student.toString());
    System.out.println();
    /

    * json字符串转List对象
    * 字符串:对象数组[{“age”:24,“name”:“bob”},{“age”:23,“name”:“lily”}]
    * 如果字符串是 对象,比如 {‘name’:‘曹新晴’,‘age’:‘30’}”,就需要先转换成Map,再转换成List
    */
    System.out.println(“json字符串转List对象”);
    String jsonStr2 = “[{‘age’:24,‘name’:‘bob’},{‘age’:23,‘name’:‘lily’}]”;
    List students = JSON.parseArray(jsonStr2, Student.class);
    System.out.println(students.toString());
    System.out.println();
    System.out.println(“json字符串转复杂java对象”);
    String jsonStr3 = “{‘username’:‘StudentGroup’,‘stus’:[{‘age’:24,‘name’:‘bob’},{‘age’:23,‘name’:‘lily’}]}”;
    StudentGroup studentGroup = JSON.parseObject(jsonStr3, StudentGroup.class);
    System.out.println(studentGroup);
    String jsonStr4 = “[{‘username’:‘StudentGroup’,‘stus’:[{‘age’:24,‘name’:‘bob’},{‘age’:23,‘name’:‘lily’}]},{‘username’:‘StudentGroup2’,‘stus’:[{‘age’:34,‘name’:‘bob2’},{‘age’:33,‘name’:‘lily2’}]}]”;
    List parseArray = JSON.parseArray(jsonStr4, StudentGroup.class);
    System.out.println(“parseArray:”+parseArray);
    System.out.println();
    System.out.println(“json字符串转Map对象”);
    String jsonStr5 =“{‘mobilephone’:‘13517315120’,‘pwd’:‘315120’}”;
    Map map = JSON.parseObject(jsonStr5, Map.class);
    }
    }

    12.内存分配

    堆内存

    用来存放由new创建的对象实例和数组。注意创建出来的对象只包含属于各自的成员变量,并不包括成员方法。访问对象需靠引用变量(栈中创建),常量池存在于堆中。

    栈内存

    栈用于存储程序运行时在方法中声明的所有局部变量(栈主要存储方法中的局部变量)包括:1.用来保存基本数据类型的值。特点:栈内存的数据用完就释放

    方法区(静态区)

    用于存放类的各种信息(包括方法)都在方法区存储。(将类的成员都加载到方法区)和static变量

    13.数据类型

    1. 基本数据类型
    a) 数字
    i. 整数:byte(1个字节) short(2个字节) int(4个字节,整型常量默认该类型) long(8个字节)
    ii. 浮点数:float(4个字节) double(8个字节,浮点常量默认为该类型)
    b) 字符 char(2个字节)
    c) 布尔 boolean(1位)
    2.引用类型(4个字节)
    接口、对象、类、数组、字符串String、集合等
    1:java开发过程中整型用int、小数用double、布尔用boolean;
    2:类型转换都是小范围向大范围转换,大范围往小范围转化需要用到强制转换

    14.字符串的常用操作

    ● charAt(i) 获取指定位置的字符
    ● length() 字符串长度,字符的数量
    ● indexof()找第一个子串出现的初始位置,找不到返回-1
    ● indexof(子串,start)从执行位置向后找
    ● lastIndexof(子串) 从后向前找
    ● subString(start)截取start到末尾
    ● subString[start,end )截取[start,end )范围
    ● trim()去除两端的空白字符
    ● matches()用来判断是否匹配正则表达式
    Java中的 split 函数是用于按指定字符(串)或正则去分割某个字符串,结果以字符串数组形式返回;
    StringBuilder: 可变的字符序列,封装char[]数组,提供了一组方法,可以对内部封装的字符进行修改,常用来代替字符串做高效的字符串连接
    ● append() 追加字符内容,内部数组默认初始容量16,放满后翻倍+2;

    15.集合

    1.List特点
    元素有序、且可重复的集合,集合中的每个元素都有其对应的顺序索引;
    允许使用重复元素,可以通过索引来访问指定位置的集合元素;
    默认按元素的添加顺序设置元素的索引。
    相关实现类:ArrayList基于数组结构实现,使用在查询比较多的场合下,基本操作如下:
    add(E e)添加元素
    add(int index, E element)添加元素到指定位置,ArrayList元素下标从0开始
    size()获取ArrayList长度
    get(int index)获取指定位置的元素
    addAll(Collection c)添加另外一个集合
    addAll(int index,Collection c)添加另外一个集合到指定位置
    clear()清空
    set(int index, E element)设置某个位置的元素
    contains(Object o)判断集合中是否包含某个元素
    remove(int index)删除指定位置的元素
    remove(Object o)删除特定元素
    indexOf(Object o)返回元素的索引
    遍历:
    //通过下标遍历集合
    for (int i = 0; i < list.size(); i++) {
    System.out.println(list.get(i));
    }
    //通过增强for循环
    for (String Str : list) {
    System.out.println(Str);
    }
    //通过迭代器遍历集合
    Iterator it = list.iterator();
    while (it.hasNext()) {
    System.out.println(it.next());
    }
    2.Set特点
    无序且不可重复
    HashSet是Set接口的典型实现,大多数时候使用Set集合时都使用这个实现类
    3.Map特点
    所有的key构成的集合是Set:无序的、不可重复的
    HashMap是Map接口使用频率最高的实现类
    常用方法:
    添加、删除、修改操作
    put(Object key,Object value):将指定key-value添加到(或修改)当前map对象中
    putAll(Map m):将m中的所有key-value对存放到当前map中
    remove(Object key):移除指定key的key-value对,并返回value
    clear():清空当前Map中的所有数据
    查询操作
    get(Object key):获取指定key对应的value
    containsKey(Object key):是否包含指定的key
    containsValue(Object value):是否包含指定的value
    size():返回map中key-value对的个数
    isEmpty():判断当前map是否为空
    equals(Object obj):判断当前map和参数对象obj是否相等
    其他操作
    keySet():返回所有key构成的Set集合
    Set set = map.keySet();//遍历map所有的key
    for (String s : set) {
    System.out.println(s);
    }
    values():返回所有value构成的Collection集合
    Collection values = map.values(); //遍历map所有的value
    for (String value : values) {
    System.out.println(value);
    }
    entrySet():返回所有key-value对构成的Set集合
    Set keys = map.keySet();// 遍历map所有的键值对
    for (String k : keys) {
    String v = map.get(k);
    System.out.println(k + “:” + v);
    }

  • 相关阅读:
    带你揭开神秘的Javascript AST面纱之Babel AST 四件套的使用方法
    [Git] 系列三随意修改提交记录以及一些技巧
    【ARM裸机】ARM入门
    静态路由+PAT转换(讲解+实验)
    基于桶的排序之计数排序
    java基于springboot+Vue社区居民医疗健康网站
    Hive存储格式之RCFile详解,RCFile的过去现在和未来
    学习-Java输入输出之随机IO流之向文件中追加内容
    java毕业生设计校园闲置物品交换平台系统计算机源码+系统+mysql+调试部署+lw
    CICD—Jenkins Gitlab自动化打包java到K8S
  • 原文地址:https://blog.csdn.net/Caoqingqing521/article/details/134290007