精华内容
下载资源
问答
  • Java基础知识面试题(2020最新版)

    万次阅读 多人点赞 2020-02-19 12:11:27
    文章目录Java概述何为编程什么是Javajdk1.5之后的三大版本JVM、JRE和JDK的关系什么是跨平台性?原理是什么Java语言有哪些特点什么是字节码?采用字节码的最大好处是什么什么是Java程序的主类?应用程序和小程序的...

    Java面试总结(2021优化版)已发布在个人微信公众号【技术人成长之路】,优化版首先修正了读者反馈的部分答案存在的错误,同时根据最新面试总结,删除了低频问题,添加了一些常见面试题,对文章进行了精简优化,欢迎大家关注!😊😊

    【技术人成长之路】,助力技术人成长!更多精彩文章第一时间在公众号发布哦!

    文章目录

    Java面试总结汇总,整理了包括Java基础知识,集合容器,并发编程,JVM,常用开源框架Spring,MyBatis,数据库,中间件等,包含了作为一个Java工程师在面试中需要用到或者可能用到的绝大部分知识。欢迎大家阅读,本人见识有限,写的博客难免有错误或者疏忽的地方,还望各位大佬指点,在此表示感激不尽。文章持续更新中…

    序号内容链接地址
    1Java基础知识面试题(2020最新版)https://thinkwon.blog.csdn.net/article/details/104390612
    2Java集合容器面试题(2020最新版)https://thinkwon.blog.csdn.net/article/details/104588551
    3Java异常面试题(2020最新版)https://thinkwon.blog.csdn.net/article/details/104390689
    4并发编程面试题(2020最新版)https://thinkwon.blog.csdn.net/article/details/104863992
    5JVM面试题(2020最新版)https://thinkwon.blog.csdn.net/article/details/104390752
    6Spring面试题(2020最新版)https://thinkwon.blog.csdn.net/article/details/104397516
    7Spring MVC面试题(2020最新版)https://thinkwon.blog.csdn.net/article/details/104397427
    8Spring Boot面试题(2020最新版)https://thinkwon.blog.csdn.net/article/details/104397299
    9Spring Cloud面试题(2020最新版)https://thinkwon.blog.csdn.net/article/details/104397367
    10MyBatis面试题(2020最新版)https://thinkwon.blog.csdn.net/article/details/101292950
    11Redis面试题(2020最新版)https://thinkwon.blog.csdn.net/article/details/103522351
    12MySQL数据库面试题(2020最新版)https://thinkwon.blog.csdn.net/article/details/104778621
    13消息中间件MQ与RabbitMQ面试题(2020最新版)https://thinkwon.blog.csdn.net/article/details/104588612
    14Dubbo面试题(2020最新版)https://thinkwon.blog.csdn.net/article/details/104390006
    15Linux面试题(2020最新版)https://thinkwon.blog.csdn.net/article/details/104588679
    16Tomcat面试题(2020最新版)https://thinkwon.blog.csdn.net/article/details/104397665
    17ZooKeeper面试题(2020最新版)https://thinkwon.blog.csdn.net/article/details/104397719
    18Netty面试题(2020最新版)https://thinkwon.blog.csdn.net/article/details/104391081
    19架构设计&分布式&数据结构与算法面试题(2020最新版)https://thinkwon.blog.csdn.net/article/details/105870730

    Java概述

    何为编程

    编程就是让计算机为解决某个问题而使用某种程序设计语言编写程序代码,并最终得到结果的过程。

    为了使计算机能够理解人的意图,人类就必须要将需解决的问题的思路、方法、和手段通过计算机能够理解的形式告诉计算机,使得计算机能够根据人的指令一步一步去工作,完成某种特定的任务。这种人和计算机之间交流的过程就是编程。

    什么是Java

    Java是一门面向对象编程语言,不仅吸收了C++语言的各种优点,还摒弃了C++里难以理解的多继承、指针等概念,因此Java语言具有功能强大和简单易用两个特征。Java语言作为静态面向对象编程语言的代表,极好地实现了面向对象理论,允许程序员以优雅的思维方式进行复杂的编程 。

    jdk1.5之后的三大版本

    • Java SE(J2SE,Java 2 Platform Standard Edition,标准版)
      Java SE 以前称为 J2SE。它允许开发和部署在桌面、服务器、嵌入式环境和实时环境中使用的 Java 应用程序。Java SE 包含了支持 Java Web 服务开发的类,并为Java EE和Java ME提供基础。
    • Java EE(J2EE,Java 2 Platform Enterprise Edition,企业版)
      Java EE 以前称为 J2EE。企业版本帮助开发和部署可移植、健壮、可伸缩且安全的服务器端Java 应用程序。Java EE 是在 Java SE 的基础上构建的,它提供 Web 服务、组件模型、管理和通信 API,可以用来实现企业级的面向服务体系结构(service-oriented architecture,SOA)和 Web2.0应用程序。2018年2月,Eclipse 宣布正式将 JavaEE 更名为 JakartaEE
    • Java ME(J2ME,Java 2 Platform Micro Edition,微型版)
      Java ME 以前称为 J2ME。Java ME 为在移动设备和嵌入式设备(比如手机、PDA、电视机顶盒和打印机)上运行的应用程序提供一个健壮且灵活的环境。Java ME 包括灵活的用户界面、健壮的安全模型、许多内置的网络协议以及对可以动态下载的连网和离线应用程序的丰富支持。基于 Java ME 规范的应用程序只需编写一次,就可以用于许多设备,而且可以利用每个设备的本机功能。

    JVM、JRE和JDK的关系

    JVM
    Java Virtual Machine是Java虚拟机,Java程序需要运行在虚拟机上,不同的平台有自己的虚拟机,因此Java语言可以实现跨平台。

    JRE
    Java Runtime Environment包括Java虚拟机和Java程序所需的核心类库等。核心类库主要是java.lang包:包含了运行Java程序必不可少的系统类,如基本数据类型、基本数学函数、字符串处理、线程、异常处理类等,系统缺省加载这个包

    如果想要运行一个开发好的Java程序,计算机中只需要安装JRE即可。

    JDK
    Java Development Kit是提供给Java开发人员使用的,其中包含了Java的开发工具,也包括了JRE。所以安装了JDK,就无需再单独安装JRE了。其中的开发工具:编译工具(javac.exe),打包工具(jar.exe)等

    JVM&JRE&JDK关系图

    什么是跨平台性?原理是什么

    所谓跨平台性,是指java语言编写的程序,一次编译后,可以在多个系统平台上运行。

    实现原理:Java程序是通过java虚拟机在系统平台上运行的,只要该系统可以安装相应的java虚拟机,该系统就可以运行java程序。

    Java语言有哪些特点

    简单易学(Java语言的语法与C语言和C++语言很接近)

    面向对象(封装,继承,多态)

    平台无关性(Java虚拟机实现平台无关性)

    支持网络编程并且很方便(Java语言诞生本身就是为简化网络编程设计的)

    支持多线程(多线程机制使应用程序在同一时间并行执行多项任)

    健壮性(Java语言的强类型机制、异常处理、垃圾的自动收集等)

    安全性

    什么是字节码?采用字节码的最大好处是什么

    字节码:Java源代码经过虚拟机编译器编译后产生的文件(即扩展为.class的文件),它不面向任何特定的处理器,只面向虚拟机。

    采用字节码的好处

    Java语言通过字节码的方式,在一定程度上解决了传统解释型语言执行效率低的问题,同时又保留了解释型语言可移植的特点。所以Java程序运行时比较高效,而且,由于字节码并不专对一种特定的机器,因此,Java程序无须重新编译便可在多种不同的计算机上运行。

    先看下java中的编译器和解释器

    Java中引入了虚拟机的概念,即在机器和编译程序之间加入了一层抽象的虚拟机器。这台虚拟的机器在任何平台上都提供给编译程序一个的共同的接口。编译程序只需要面向虚拟机,生成虚拟机能够理解的代码,然后由解释器来将虚拟机代码转换为特定系统的机器码执行。在Java中,这种供虚拟机理解的代码叫做字节码(即扩展为.class的文件),它不面向任何特定的处理器,只面向虚拟机。每一种平台的解释器是不同的,但是实现的虚拟机是相同的。Java源程序经过编译器编译后变成字节码,字节码由虚拟机解释执行,虚拟机将每一条要执行的字节码送给解释器,解释器将其翻译成特定机器上的机器码,然后在特定的机器上运行,这就是上面提到的Java的特点的编译与解释并存的解释。

    Java源代码---->编译器---->jvm可执行的Java字节码(即虚拟指令)---->jvm---->jvm中解释器----->机器可执行的二进制机器码---->程序运行。
    

    什么是Java程序的主类?应用程序和小程序的主类有何不同?

    一个程序中可以有多个类,但只能有一个类是主类。在Java应用程序中,这个主类是指包含main()方法的类。而在Java小程序中,这个主类是一个继承自系统类JApplet或Applet的子类。应用程序的主类不一定要求是public类,但小程序的主类要求必须是public类。主类是Java程序执行的入口点。

    Java应用程序与小程序之间有那些差别?

    简单说应用程序是从主线程启动(也就是main()方法)。applet小程序没有main方法,主要是嵌在浏览器页面上运行(调用init()线程或者run()来启动),嵌入浏览器这点跟flash的小游戏类似。

    Java和C++的区别

    我知道很多人没学过C++,但是面试官就是没事喜欢拿咱们Java和C++比呀!没办法!!!就算没学过C++,也要记下来!

    • 都是面向对象的语言,都支持封装、继承和多态
    • Java不提供指针来直接访问内存,程序内存更加安全
    • Java的类是单继承的,C++支持多重继承;虽然Java的类不可以多继承,但是接口可以多继承。
    • Java有自动内存管理机制,不需要程序员手动释放无用内存

    Oracle JDK 和 OpenJDK 的对比

    1. Oracle JDK版本将每三年发布一次,而OpenJDK版本每三个月发布一次;

    2. OpenJDK 是一个参考模型并且是完全开源的,而Oracle JDK是OpenJDK的一个实现,并不是完全开源的;

    3. Oracle JDK 比 OpenJDK 更稳定。OpenJDK和Oracle JDK的代码几乎相同,但Oracle JDK有更多的类和一些错误修复。因此,如果您想开发企业/商业软件,我建议您选择Oracle JDK,因为它经过了彻底的测试和稳定。某些情况下,有些人提到在使用OpenJDK 可能会遇到了许多应用程序崩溃的问题,但是,只需切换到Oracle JDK就可以解决问题;

    4. 在响应性和JVM性能方面,Oracle JDK与OpenJDK相比提供了更好的性能;

    5. Oracle JDK不会为即将发布的版本提供长期支持,用户每次都必须通过更新到最新版本获得支持来获取最新版本;

    6. Oracle JDK根据二进制代码许可协议获得许可,而OpenJDK根据GPL v2许可获得许可。

    基础语法

    数据类型

    Java有哪些数据类型

    定义:Java语言是强类型语言,对于每一种数据都定义了明确的具体的数据类型,在内存中分配了不同大小的内存空间。

    分类

    • 基本数据类型
      • 数值型
        • 整数类型(byte,short,int,long)
        • 浮点类型(float,double)
      • 字符型(char)
      • 布尔型(boolean)
    • 引用数据类型
      • 类(class)
      • 接口(interface)
      • 数组([])

    Java基本数据类型图

    switch 是否能作用在 byte 上,是否能作用在 long 上,是否能作用在 String 上

    在 Java 5 以前,switch(expr)中,expr 只能是 byte、short、char、int。从 Java5 开始,Java 中引入了枚举类型,expr 也可以是 enum 类型,从 Java 7 开始,expr 还可以是字符串(String),但是长整型(long)在目前所有的版本中都是不可以的。

    用最有效率的方法计算 2 乘以 8

    2 << 3(左移 3 位相当于乘以 2 的 3 次方,右移 3 位相当于除以 2 的 3 次方)。

    Math.round(11.5) 等于多少?Math.round(-11.5)等于多少

    Math.round(11.5)的返回值是 12,Math.round(-11.5)的返回值是-11。四舍五入的原理是在参数上加 0.5 然后进行下取整。

    float f=3.4;是否正确

    不正确。3.4 是双精度数,将双精度型(double)赋值给浮点型(float)属于下转型(down-casting,也称为窄化)会造成精度损失,因此需要强制类型转换float f =(float)3.4; 或者写成 float f =3.4F;。

    short s1 = 1; s1 = s1 + 1;有错吗?short s1 = 1; s1 += 1;有错吗

    对于 short s1 = 1; s1 = s1 + 1;由于 1 是 int 类型,因此 s1+1 运算结果也是 int型,需要强制转换类型才能赋值给 short 型。

    而 short s1 = 1; s1 += 1;可以正确编译,因为 s1+= 1;相当于 s1 = (short(s1 + 1);其中有隐含的强制类型转换。

    编码

    Java语言采用何种编码方案?有何特点?

    Java语言采用Unicode编码标准,Unicode(标准码),它为每个字符制订了一个唯一的数值,因此在任何的语言,平台,程序都可以放心的使用。

    注释

    什么Java注释

    定义:用于解释说明程序的文字

    分类

    • 单行注释
      格式: // 注释文字
    • 多行注释
      格式: /* 注释文字 */
    • 文档注释
      格式:/** 注释文字 */

    作用

    在程序中,尤其是复杂的程序中,适当地加入注释可以增加程序的可读性,有利于程序的修改、调试和交流。注释的内容在程序编译的时候会被忽视,不会产生目标代码,注释的部分不会对程序的执行结果产生任何影响。

    注意事项:多行和文档注释都不能嵌套使用。

    访问修饰符

    访问修饰符 public,private,protected,以及不写(默认)时的区别

    定义:Java中,可以使用访问修饰符来保护对类、变量、方法和构造方法的访问。Java 支持 4 种不同的访问权限。

    分类

    private : 在同一类内可见。使用对象:变量、方法。 注意:不能修饰类(外部类)
    default (即缺省,什么也不写,不使用任何关键字): 在同一包内可见,不使用任何修饰符。使用对象:类、接口、变量、方法。
    protected : 对同一包内的类和所有子类可见。使用对象:变量、方法。 注意:不能修饰类(外部类)。
    public : 对所有类可见。使用对象:类、接口、变量、方法

    访问修饰符图

    运算符

    &和&&的区别

    &运算符有两种用法:(1)按位与;(2)逻辑与。

    &&运算符是短路与运算。逻辑与跟短路与的差别是非常巨大的,虽然二者都要求运算符左右两端的布尔值都是true 整个表达式的值才是 true。&&之所以称为短路运算,是因为如果&&左边的表达式的值是 false,右边的表达式会被直接短路掉,不会进行运算。

    注意:逻辑或运算符(|)和短路或运算符(||)的差别也是如此。

    关键字

    Java 有没有 goto

    goto 是 Java 中的保留字,在目前版本的 Java 中没有使用。

    final 有什么用?

    用于修饰类、属性和方法;

    • 被final修饰的类不可以被继承
    • 被final修饰的方法不可以被重写
    • 被final修饰的变量不可以被改变,被final修饰不可变的是变量的引用,而不是引用指向的内容,引用指向的内容是可以改变的

    final finally finalize区别

    • final可以修饰类、变量、方法,修饰类表示该类不能被继承、修饰方法表示该方法不能被重写、修饰变量表
      示该变量是一个常量不能被重新赋值。
    • finally一般作用在try-catch代码块中,在处理异常的时候,通常我们将一定要执行的代码方法finally代码块
      中,表示不管是否出现异常,该代码块都会执行,一般用来存放一些关闭资源的代码。
    • finalize是一个方法,属于Object类的一个方法,而Object类是所有类的父类,该方法一般由垃圾回收器来调
      用,当我们调用System.gc() 方法的时候,由垃圾回收器调用finalize(),回收垃圾,一个对象是否可回收的
      最后判断。

    this关键字的用法

    this是自身的一个对象,代表对象本身,可以理解为:指向对象本身的一个指针。

    this的用法在java中大体可以分为3种:

    1.普通的直接引用,this相当于是指向当前对象本身。

    2.形参与成员名字重名,用this来区分:

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    

    3.引用本类的构造函数

    class Person{
        private String name;
        private int age;
        
        public Person() {
        }
     
        public Person(String name) {
            this.name = name;
        }
        public Person(String name, int age) {
            this(name);
            this.age = age;
        }
    }
    

    super关键字的用法

    super可以理解为是指向自己超(父)类对象的一个指针,而这个超类指的是离自己最近的一个父类。

    super也有三种用法:

    1.普通的直接引用

    与this类似,super相当于是指向当前对象的父类的引用,这样就可以用super.xxx来引用父类的成员。

    2.子类中的成员变量或方法与父类中的成员变量或方法同名时,用super进行区分

    class Person{
        protected String name;
     
        public Person(String name) {
            this.name = name;
        }
     
    }
     
    class Student extends Person{
        private String name;
     
        public Student(String name, String name1) {
            super(name);
            this.name = name1;
        }
     
        public void getInfo(){
            System.out.println(this.name);      //Child
            System.out.println(super.name);     //Father
        }
     
    }
    
    public class Test {
        public static void main(String[] args) {
           Student s1 = new Student("Father","Child");
           s1.getInfo();
     
        }
    }
    

    3.引用父类构造函数

    3、引用父类构造函数

    • super(参数):调用父类中的某一个构造函数(应该为构造函数中的第一条语句)。
    • this(参数):调用本类中另一种形式的构造函数(应该为构造函数中的第一条语句)。

    this与super的区别

    • super: 它引用当前对象的直接父类中的成员(用来访问直接父类中被隐藏的父类中成员数据或函数,基类与派生类中有相同成员定义时如:super.变量名 super.成员函数据名(实参)
    • this:它代表当前对象名(在程序中易产生二义性之处,应使用this来指明当前对象;如果函数的形参与类中的成员数据同名,这时需用this来指明成员变量名)
    • super()和this()类似,区别是,super()在子类中调用父类的构造方法,this()在本类内调用本类的其它构造方法。
    • super()和this()均需放在构造方法内第一行。
    • 尽管可以用this调用一个构造器,但却不能调用两个。
    • this和super不能同时出现在一个构造函数里面,因为this必然会调用其它的构造函数,其它的构造函数必然也会有super语句的存在,所以在同一个构造函数里面有相同的语句,就失去了语句的意义,编译器也不会通过。
    • this()和super()都指的是对象,所以,均不可以在static环境中使用。包括:static变量,static方法,static语句块。
    • 从本质上讲,this是一个指向本对象的指针, 然而super是一个Java关键字。

    static存在的主要意义

    static的主要意义是在于创建独立于具体对象的域变量或者方法。以致于即使没有创建对象,也能使用属性和调用方法

    static关键字还有一个比较关键的作用就是 用来形成静态代码块以优化程序性能。static块可以置于类中的任何地方,类中可以有多个static块。在类初次被加载的时候,会按照static块的顺序来执行每个static块,并且只会执行一次。

    为什么说static块可以用来优化程序性能,是因为它的特性:只会在类加载的时候执行一次。因此,很多时候会将一些只需要进行一次的初始化操作都放在static代码块中进行。

    static的独特之处

    1、被static修饰的变量或者方法是独立于该类的任何对象,也就是说,这些变量和方法不属于任何一个实例对象,而是被类的实例对象所共享

    怎么理解 “被类的实例对象所共享” 这句话呢?就是说,一个类的静态成员,它是属于大伙的【大伙指的是这个类的多个对象实例,我们都知道一个类可以创建多个实例!】,所有的类对象共享的,不像成员变量是自个的【自个指的是这个类的单个实例对象】…我觉得我已经讲的很通俗了,你明白了咩?

    2、在该类被第一次加载的时候,就会去加载被static修饰的部分,而且只在类第一次使用时加载并进行初始化,注意这是第一次用就要初始化,后面根据需要是可以再次赋值的。

    3、static变量值在类加载的时候分配空间,以后创建类对象的时候不会重新分配。赋值的话,是可以任意赋值的!

    4、被static修饰的变量或者方法是优先于对象存在的,也就是说当一个类加载完毕之后,即便没有创建对象,也可以去访问。

    static应用场景

    因为static是被类的实例对象所共享,因此如果某个成员变量是被所有对象所共享的,那么这个成员变量就应该定义为静态变量

    因此比较常见的static应用场景有:

    1、修饰成员变量 2、修饰成员方法 3、静态代码块 4、修饰类【只能修饰内部类也就是静态内部类】 5、静态导包

    static注意事项

    1、静态只能访问静态。 2、非静态既可以访问非静态的,也可以访问静态的。

    流程控制语句

    break ,continue ,return 的区别及作用

    break 跳出总上一层循环,不再执行循环(结束当前的循环体)

    continue 跳出本次循环,继续执行下次循环(结束正在执行的循环 进入下一个循环条件)

    return 程序返回,不再执行下面的代码(结束当前的方法 直接返回)

    在 Java 中,如何跳出当前的多重嵌套循环

    在Java中,要想跳出多重循环,可以在外面的循环语句前定义一个标号,然后在里层循环体的代码中使用带有标号的break 语句,即可跳出外层循环。例如:

    public static void main(String[] args) {
        ok:
        for (int i = 0; i < 10; i++) {
            for (int j = 0; j < 10; j++) {
                System.out.println("i=" + i + ",j=" + j);
                if (j == 5) {
                    break ok;
                }
    
            }
        }
    }
    

    面向对象

    面向对象概述

    面向对象和面向过程的区别

    面向过程

    优点:性能比面向对象高,因为类调用时需要实例化,开销比较大,比较消耗资源;比如单片机、嵌入式开发、Linux/Unix等一般采用面向过程开发,性能是最重要的因素。

    缺点:没有面向对象易维护、易复用、易扩展

    面向对象

    优点:易维护、易复用、易扩展,由于面向对象有封装、继承、多态性的特性,可以设计出低耦合的系统,使系统更加灵活、更加易于维护

    缺点:性能比面向过程低

    面向过程是具体化的,流程化的,解决一个问题,你需要一步一步的分析,一步一步的实现。

    面向对象是模型化的,你只需抽象出一个类,这是一个封闭的盒子,在这里你拥有数据也拥有解决问题的方法。需要什么功能直接使用就可以了,不必去一步一步的实现,至于这个功能是如何实现的,管我们什么事?我们会用就可以了。

    面向对象的底层其实还是面向过程,把面向过程抽象成类,然后封装,方便我们使用的就是面向对象了。

    面向对象三大特性

    面向对象的特征有哪些方面

    面向对象的特征主要有以下几个方面

    抽象:抽象是将一类对象的共同特征总结出来构造类的过程,包括数据抽象和行为抽象两方面。抽象只关注对象有哪些属性和行为,并不关注这些行为的细节是什么。

    封装

    封装把一个对象的属性私有化,同时提供一些可以被外界访问的属性的方法,如果属性不想被外界访问,我们大可不必提供方法给外界访问。但是如果一个类没有提供给外界访问的方法,那么这个类也没有什么意义了。

    继承

    继承是使用已存在的类的定义作为基础建立新类的技术,新类的定义可以增加新的数据或新的功能,也可以用父类的功能,但不能选择性地继承父类。通过使用继承我们能够非常方便地复用以前的代码。

    关于继承如下 3 点请记住:

    1. 子类拥有父类非 private 的属性和方法。

    2. 子类可以拥有自己属性和方法,即子类可以对父类进行扩展。

    3. 子类可以用自己的方式实现父类的方法。(以后介绍)。

    多态

    所谓多态就是指程序中定义的引用变量所指向的具体类型和通过该引用变量发出的方法调用在编程时并不确定,而是在程序运行期间才确定,即一个引用变量到底会指向哪个类的实例对象,该引用变量发出的方法调用到底是哪个类中实现的方法,必须在由程序运行期间才能决定。

    在Java中有两种形式可以实现多态:继承(多个子类对同一方法的重写)和接口(实现接口并覆盖接口中同一方法)。

    其中Java 面向对象编程三大特性:封装 继承 多态

    封装:隐藏对象的属性和实现细节,仅对外提供公共访问方式,将变化隔离,便于使用,提高复用性和安全性。

    继承:继承是使用已存在的类的定义作为基础建立新类的技术,新类的定义可以增加新的数据或新的功能,也可以用父类的功能,但不能选择性地继承父类。通过使用继承可以提高代码复用性。继承是多态的前提。

    关于继承如下 3 点请记住

    1. 子类拥有父类非 private 的属性和方法。

    2. 子类可以拥有自己属性和方法,即子类可以对父类进行扩展。

    3. 子类可以用自己的方式实现父类的方法。

    多态性:父类或接口定义的引用变量可以指向子类或具体实现类的实例对象。提高了程序的拓展性。

    在Java中有两种形式可以实现多态:继承(多个子类对同一方法的重写)和接口(实现接口并覆盖接口中同一方法)。

    方法重载(overload)实现的是编译时的多态性(也称为前绑定),而方法重写(override)实现的是运行时的多态性(也称为后绑定)。

    一个引用变量到底会指向哪个类的实例对象,该引用变量发出的方法调用到底是哪个类中实现的方法,必须在由程序运行期间才能决定。运行时的多态是面向对象最精髓的东西,要实现多态需要做两件事:

    • 方法重写(子类继承父类并重写父类中已有的或抽象的方法);
    • 对象造型(用父类型引用子类型对象,这样同样的引用调用同样的方法就会根据子类对象的不同而表现出不同的行为)。

    什么是多态机制?Java语言是如何实现多态的?

    所谓多态就是指程序中定义的引用变量所指向的具体类型和通过该引用变量发出的方法调用在编程时并不确定,而是在程序运行期间才确定,即一个引用变量倒底会指向哪个类的实例对象,该引用变量发出的方法调用到底是哪个类中实现的方法,必须在由程序运行期间才能决定。因为在程序运行时才确定具体的类,这样,不用修改源程序代码,就可以让引用变量绑定到各种不同的类实现上,从而导致该引用调用的具体方法随之改变,即不修改程序代码就可以改变程序运行时所绑定的具体代码,让程序可以选择多个运行状态,这就是多态性。

    多态分为编译时多态和运行时多态。其中编辑时多态是静态的,主要是指方法的重载,它是根据参数列表的不同来区分不同的函数,通过编辑之后会变成两个不同的函数,在运行时谈不上多态。而运行时多态是动态的,它是通过动态绑定来实现的,也就是我们所说的多态性。

    多态的实现

    Java实现多态有三个必要条件:继承、重写、向上转型。

    继承:在多态中必须存在有继承关系的子类和父类。

    重写:子类对父类中某些方法进行重新定义,在调用这些方法时就会调用子类的方法。

    向上转型:在多态中需要将子类的引用赋给父类对象,只有这样该引用才能够具备技能调用父类的方法和子类的方法。

    只有满足了上述三个条件,我们才能够在同一个继承结构中使用统一的逻辑实现代码处理不同的对象,从而达到执行不同的行为。

    对于Java而言,它多态的实现机制遵循一个原则:当超类对象引用变量引用子类对象时,被引用对象的类型而不是引用变量的类型决定了调用谁的成员方法,但是这个被调用的方法必须是在超类中定义过的,也就是说被子类覆盖的方法。

    面向对象五大基本原则是什么(可选)

    • 单一职责原则SRP(Single Responsibility Principle)
      类的功能要单一,不能包罗万象,跟杂货铺似的。
    • 开放封闭原则OCP(Open-Close Principle)
      一个模块对于拓展是开放的,对于修改是封闭的,想要增加功能热烈欢迎,想要修改,哼,一万个不乐意。
    • 里式替换原则LSP(the Liskov Substitution Principle LSP)
      子类可以替换父类出现在父类能够出现的任何地方。比如你能代表你爸去你姥姥家干活。哈哈~~
    • 依赖倒置原则DIP(the Dependency Inversion Principle DIP)
      高层次的模块不应该依赖于低层次的模块,他们都应该依赖于抽象。抽象不应该依赖于具体实现,具体实现应该依赖于抽象。就是你出国要说你是中国人,而不能说你是哪个村子的。比如说中国人是抽象的,下面有具体的xx省,xx市,xx县。你要依赖的抽象是中国人,而不是你是xx村的。
    • 接口分离原则ISP(the Interface Segregation Principle ISP)
      设计时采用多个与特定客户类有关的接口比采用一个通用的接口要好。就比如一个手机拥有打电话,看视频,玩游戏等功能,把这几个功能拆分成不同的接口,比在一个接口里要好的多。

    类与接口

    抽象类和接口的对比

    抽象类是用来捕捉子类的通用特性的。接口是抽象方法的集合。

    从设计层面来说,抽象类是对类的抽象,是一种模板设计,接口是行为的抽象,是一种行为的规范。

    相同点

    • 接口和抽象类都不能实例化
    • 都位于继承的顶端,用于被其他实现或继承
    • 都包含抽象方法,其子类都必须覆写这些抽象方法

    不同点

    参数抽象类接口
    声明抽象类使用abstract关键字声明接口使用interface关键字声明
    实现子类使用extends关键字来继承抽象类。如果子类不是抽象类的话,它需要提供抽象类中所有声明的方法的实现子类使用implements关键字来实现接口。它需要提供接口中所有声明的方法的实现
    构造器抽象类可以有构造器接口不能有构造器
    访问修饰符抽象类中的方法可以是任意访问修饰符接口方法默认修饰符是public。并且不允许定义为 private 或者 protected
    多继承一个类最多只能继承一个抽象类一个类可以实现多个接口
    字段声明抽象类的字段声明可以是任意的接口的字段默认都是 static 和 final 的

    备注:Java8中接口中引入默认方法和静态方法,以此来减少抽象类和接口之间的差异。

    现在,我们可以为接口提供默认实现的方法了,并且不用强制子类来实现它。

    接口和抽象类各有优缺点,在接口和抽象类的选择上,必须遵守这样一个原则:

    • 行为模型应该总是通过接口而不是抽象类定义,所以通常是优先选用接口,尽量少用抽象类。
    • 选择抽象类的时候通常是如下情况:需要定义子类的行为,又要为子类提供通用的功能。

    普通类和抽象类有哪些区别?

    • 普通类不能包含抽象方法,抽象类可以包含抽象方法。
    • 抽象类不能直接实例化,普通类可以直接实例化。

    抽象类能使用 final 修饰吗?

    不能,定义抽象类就是让其他类继承的,如果定义为 final 该类就不能被继承,这样彼此就会产生矛盾,所以 final 不能修饰抽象类

    创建一个对象用什么关键字?对象实例与对象引用有何不同?

    new关键字,new创建对象实例(对象实例在堆内存中),对象引用指向对象实例(对象引用存放在栈内存中)。一个对象引用可以指向0个或1个对象(一根绳子可以不系气球,也可以系一个气球);一个对象可以有n个引用指向它(可以用n条绳子系住一个气球)

    变量与方法

    成员变量与局部变量的区别有哪些

    变量:在程序执行的过程中,在某个范围内其值可以发生改变的量。从本质上讲,变量其实是内存中的一小块区域

    成员变量:方法外部,类内部定义的变量

    局部变量:类的方法中的变量。

    成员变量和局部变量的区别

    作用域

    成员变量:针对整个类有效。
    局部变量:只在某个范围内有效。(一般指的就是方法,语句体内)

    存储位置

    成员变量:随着对象的创建而存在,随着对象的消失而消失,存储在堆内存中。
    局部变量:在方法被调用,或者语句被执行的时候存在,存储在栈内存中。当方法调用完,或者语句结束后,就自动释放。

    生命周期

    成员变量:随着对象的创建而存在,随着对象的消失而消失
    局部变量:当方法调用完,或者语句结束后,就自动释放。

    初始值

    成员变量:有默认初始值。

    局部变量:没有默认初始值,使用前必须赋值。

    使用原则

    在使用变量时需要遵循的原则为:就近原则
    首先在局部范围找,有就使用;接着在成员位置找。

    在Java中定义一个不做事且没有参数的构造方法的作用

    Java程序在执行子类的构造方法之前,如果没有用super()来调用父类特定的构造方法,则会调用父类中“没有参数的构造方法”。因此,如果父类中只定义了有参数的构造方法,而在子类的构造方法中又没有用super()来调用父类中特定的构造方法,则编译时将发生错误,因为Java程序在父类中找不到没有参数的构造方法可供执行。解决办法是在父类里加上一个不做事且没有参数的构造方法。

    在调用子类构造方法之前会先调用父类没有参数的构造方法,其目的是?

    帮助子类做初始化工作。

    一个类的构造方法的作用是什么?若一个类没有声明构造方法,改程序能正确执行吗?为什么?

    主要作用是完成对类对象的初始化工作。可以执行。因为一个类即使没有声明构造方法也会有默认的不带参数的构造方法。

    构造方法有哪些特性?

    名字与类名相同;

    没有返回值,但不能用void声明构造函数;

    生成类的对象时自动执行,无需调用。

    静态变量和实例变量区别

    静态变量: 静态变量由于不属于任何实例对象,属于类的,所以在内存中只会有一份,在类的加载过程中,JVM只为静态变量分配一次内存空间。

    实例变量: 每次创建对象,都会为每个对象分配成员变量内存空间,实例变量是属于实例对象的,在内存中,创建几次对象,就有几份成员变量。

    静态变量与普通变量区别

    static变量也称作静态变量,静态变量和非静态变量的区别是:静态变量被所有的对象所共享,在内存中只有一个副本,它当且仅当在类初次加载时会被初始化。而非静态变量是对象所拥有的,在创建对象的时候被初始化,存在多个副本,各个对象拥有的副本互不影响。

    还有一点就是static成员变量的初始化顺序按照定义的顺序进行初始化。

    静态方法和实例方法有何不同?

    静态方法和实例方法的区别主要体现在两个方面:

    1. 在外部调用静态方法时,可以使用"类名.方法名"的方式,也可以使用"对象名.方法名"的方式。而实例方法只有后面这种方式。也就是说,调用静态方法可以无需创建对象。
    2. 静态方法在访问本类的成员时,只允许访问静态成员(即静态成员变量和静态方法),而不允许访问实例成员变量和实例方法;实例方法则无此限制

    在一个静态方法内调用一个非静态成员为什么是非法的?

    由于静态方法可以不通过对象进行调用,因此在静态方法里,不能调用其他非静态变量,也不可以访问非静态变量成员。

    什么是方法的返回值?返回值的作用是什么?

    方法的返回值是指我们获取到的某个方法体中的代码执行后产生的结果!(前提是该方法可能产生结果)。返回值的作用:接收出结果,使得它可以用于其他的操作!

    内部类

    什么是内部类?

    在Java中,可以将一个类的定义放在另外一个类的定义内部,这就是内部类。内部类本身就是类的一个属性,与其他属性定义方式一致。

    内部类的分类有哪些

    内部类可以分为四种:成员内部类、局部内部类、匿名内部类和静态内部类

    静态内部类

    定义在类内部的静态类,就是静态内部类。

    public class Outer {
    
        private static int radius = 1;
    
        static class StaticInner {
            public void visit() {
                System.out.println("visit outer static  variable:" + radius);
            }
        }
    }
    

    静态内部类可以访问外部类所有的静态变量,而不可访问外部类的非静态变量;静态内部类的创建方式,new 外部类.静态内部类(),如下:

    Outer.StaticInner inner = new Outer.StaticInner();
    inner.visit();
    
    成员内部类

    定义在类内部,成员位置上的非静态类,就是成员内部类。

    public class Outer {
    
        private static  int radius = 1;
        private int count =2;
        
         class Inner {
            public void visit() {
                System.out.println("visit outer static  variable:" + radius);
                System.out.println("visit outer   variable:" + count);
            }
        }
    }
    

    成员内部类可以访问外部类所有的变量和方法,包括静态和非静态,私有和公有。成员内部类依赖于外部类的实例,它的创建方式外部类实例.new 内部类(),如下:

    Outer outer = new Outer();
    Outer.Inner inner = outer.new Inner();
    inner.visit();
    
    局部内部类

    定义在方法中的内部类,就是局部内部类。

    public class Outer {
    
        private  int out_a = 1;
        private static int STATIC_b = 2;
    
        public void testFunctionClass(){
            int inner_c =3;
            class Inner {
                private void fun(){
                    System.out.println(out_a);
                    System.out.println(STATIC_b);
                    System.out.println(inner_c);
                }
            }
            Inner  inner = new Inner();
            inner.fun();
        }
        public static void testStaticFunctionClass(){
            int d =3;
            class Inner {
                private void fun(){
                    // System.out.println(out_a); 编译错误,定义在静态方法中的局部类不可以访问外部类的实例变量
                    System.out.println(STATIC_b);
                    System.out.println(d);
                }
            }
            Inner  inner = new Inner();
            inner.fun();
        }
    }
    

    定义在实例方法中的局部类可以访问外部类的所有变量和方法,定义在静态方法中的局部类只能访问外部类的静态变量和方法。局部内部类的创建方式,在对应方法内,new 内部类(),如下:

     public static void testStaticFunctionClass(){
        class Inner {
        }
        Inner  inner = new Inner();
     }
    
    匿名内部类

    匿名内部类就是没有名字的内部类,日常开发中使用的比较多。

    public class Outer {
    
        private void test(final int i) {
            new Service() {
                public void method() {
                    for (int j = 0; j < i; j++) {
                        System.out.println("匿名内部类" );
                    }
                }
            }.method();
        }
     }
     //匿名内部类必须继承或实现一个已有的接口 
     interface Service{
        void method();
    }
    

    除了没有名字,匿名内部类还有以下特点:

    • 匿名内部类必须继承一个抽象类或者实现一个接口。
    • 匿名内部类不能定义任何静态成员和静态方法。
    • 当所在的方法的形参需要被匿名内部类使用时,必须声明为 final。
    • 匿名内部类不能是抽象的,它必须要实现继承的类或者实现的接口的所有抽象方法。

    匿名内部类创建方式:

    new/接口{ 
      //匿名内部类实现部分
    }
    

    内部类的优点

    我们为什么要使用内部类呢?因为它有以下优点:

    • 一个内部类对象可以访问创建它的外部类对象的内容,包括私有数据!
    • 内部类不为同一包的其他类所见,具有很好的封装性;
    • 内部类有效实现了“多重继承”,优化 java 单继承的缺陷。
    • 匿名内部类可以很方便的定义回调。

    内部类有哪些应用场景

    1. 一些多算法场合
    2. 解决一些非面向对象的语句块。
    3. 适当使用内部类,使得代码更加灵活和富有扩展性。
    4. 当某个类除了它的外部类,不再被其他的类使用时。

    局部内部类和匿名内部类访问局部变量的时候,为什么变量必须要加上final?

    局部内部类和匿名内部类访问局部变量的时候,为什么变量必须要加上final呢?它内部原理是什么呢?

    先看这段代码:

    public class Outer {
    
        void outMethod(){
            final int a =10;
            class Inner {
                void innerMethod(){
                    System.out.println(a);
                }
    
            }
        }
    }
    

    以上例子,为什么要加final呢?是因为生命周期不一致, 局部变量直接存储在栈中,当方法执行结束后,非final的局部变量就被销毁。而局部内部类对局部变量的引用依然存在,如果局部内部类要调用局部变量时,就会出错。加了final,可以确保局部内部类使用的变量与外层的局部变量区分开,解决了这个问题。

    内部类相关,看程序说出运行结果

    public class Outer {
        private int age = 12;
    
        class Inner {
            private int age = 13;
            public void print() {
                int age = 14;
                System.out.println("局部变量:" + age);
                System.out.println("内部类变量:" + this.age);
                System.out.println("外部类变量:" + Outer.this.age);
            }
        }
    
        public static void main(String[] args) {
            Outer.Inner in = new Outer().new Inner();
            in.print();
        }
    
    }
    

    运行结果:

    局部变量:14
    内部类变量:13
    外部类变量:12
    

    重写与重载

    构造器(constructor)是否可被重写(override)

    构造器不能被继承,因此不能被重写,但可以被重载。

    重载(Overload)和重写(Override)的区别。重载的方法能否根据返回类型进行区分?

    方法的重载和重写都是实现多态的方式,区别在于前者实现的是编译时的多态性,而后者实现的是运行时的多态性。

    重载:发生在同一个类中,方法名相同参数列表不同(参数类型不同、个数不同、顺序不同),与方法返回值和访问修饰符无关,即重载的方法不能根据返回类型进行区分

    重写:发生在父子类中,方法名、参数列表必须相同,返回值小于等于父类,抛出的异常小于等于父类,访问修饰符大于等于父类(里氏代换原则);如果父类方法访问修饰符为private则子类中就不是重写。

    对象相等判断

    == 和 equals 的区别是什么

    == : 它的作用是判断两个对象的地址是不是相等。即,判断两个对象是不是同一个对象。(基本数据类型 == 比较的是值,引用数据类型 == 比较的是内存地址)

    equals() : 它的作用也是判断两个对象是否相等。但它一般有两种使用情况:

    情况1:类没有覆盖 equals() 方法。则通过 equals() 比较该类的两个对象时,等价于通过“==”比较这两个对象。

    情况2:类覆盖了 equals() 方法。一般,我们都覆盖 equals() 方法来两个对象的内容相等;若它们的内容相等,则返回 true (即,认为这两个对象相等)。

    举个例子:

    public class test1 {
        public static void main(String[] args) {
            String a = new String("ab"); // a 为一个引用
            String b = new String("ab"); // b为另一个引用,对象的内容一样
            String aa = "ab"; // 放在常量池中
            String bb = "ab"; // 从常量池中查找
            if (aa == bb) // true
                System.out.println("aa==bb");
            if (a == b) // false,非同一对象
                System.out.println("a==b");
            if (a.equals(b)) // true
                System.out.println("aEQb");
            if (42 == 42.0) { // true
                System.out.println("true");
            }
        }
    }
    

    说明:

    • String中的equals方法是被重写过的,因为object的equals方法是比较的对象的内存地址,而String的equals方法比较的是对象的值。
    • 当创建String类型的对象时,虚拟机会在常量池中查找有没有已经存在的值和要创建的值相同的对象,如果有就把它赋给当前引用。如果没有就在常量池中重新创建一个String对象。

    hashCode 与 equals (重要)

    HashSet如何检查重复

    两个对象的 hashCode() 相同,则 equals() 也一定为 true,对吗?

    hashCode和equals方法的关系

    面试官可能会问你:“你重写过 hashcode 和 equals 么,为什么重写equals时必须重写hashCode方法?”

    hashCode()介绍

    hashCode() 的作用是获取哈希码,也称为散列码;它实际上是返回一个int整数。这个哈希码的作用是确定该对象在哈希表中的索引位置。hashCode() 定义在JDK的Object.java中,这就意味着Java中的任何类都包含有hashCode()函数。

    散列表存储的是键值对(key-value),它的特点是:能根据“键”快速的检索出对应的“值”。这其中就利用到了散列码!(可以快速找到所需要的对象)

    为什么要有 hashCode

    我们以“HashSet 如何检查重复”为例子来说明为什么要有 hashCode

    当你把对象加入 HashSet 时,HashSet 会先计算对象的 hashcode 值来判断对象加入的位置,同时也会与其他已经加入的对象的 hashcode 值作比较,如果没有相符的hashcode,HashSet会假设对象没有重复出现。但是如果发现有相同 hashcode 值的对象,这时会调用 equals()方法来检查 hashcode 相等的对象是否真的相同。如果两者相同,HashSet 就不会让其加入操作成功。如果不同的话,就会重新散列到其他位置。(摘自我的Java启蒙书《Head first java》第二版)。这样我们就大大减少了 equals 的次数,相应就大大提高了执行速度。

    hashCode()与equals()的相关规定

    如果两个对象相等,则hashcode一定也是相同的

    两个对象相等,对两个对象分别调用equals方法都返回true

    两个对象有相同的hashcode值,它们也不一定是相等的

    因此,equals 方法被覆盖过,则 hashCode 方法也必须被覆盖

    hashCode() 的默认行为是对堆上的对象产生独特值。如果没有重写 hashCode(),则该 class 的两个对象无论如何都不会相等(即使这两个对象指向相同的数据)

    对象的相等与指向他们的引用相等,两者有什么不同?

    对象的相等 比的是内存中存放的内容是否相等而 引用相等 比较的是他们指向的内存地址是否相等。

    值传递

    当一个对象被当作参数传递到一个方法后,此方法可改变这个对象的属性,并可返回变化后的结果,那么这里到底是值传递还是引用传递

    是值传递。Java 语言的方法调用只支持参数的值传递。当一个对象实例作为一个参数被传递到方法中时,参数的值就是对该对象的引用。对象的属性可以在被调用过程中被改变,但对对象引用的改变是不会影响到调用者的

    为什么 Java 中只有值传递

    首先回顾一下在程序设计语言中有关将参数传递给方法(或函数)的一些专业术语。按值调用(call by value)表示方法接收的是调用者提供的值,而按引用调用(call by reference)表示方法接收的是调用者提供的变量地址。一个方法可以修改传递引用所对应的变量值,而不能修改传递值调用所对应的变量值。 它用来描述各种程序设计语言(不只是Java)中方法参数传递方式。

    Java程序设计语言总是采用按值调用。也就是说,方法得到的是所有参数值的一个拷贝,也就是说,方法不能修改传递给它的任何参数变量的内容。

    下面通过 3 个例子来给大家说明

    example 1

    public static void main(String[] args) {
        int num1 = 10;
        int num2 = 20;
    
        swap(num1, num2);
    
        System.out.println("num1 = " + num1);
        System.out.println("num2 = " + num2);
    }
    
    public static void swap(int a, int b) {
        int temp = a;
        a = b;
        b = temp;
    
        System.out.println("a = " + a);
        System.out.println("b = " + b);
    }
    

    结果

    a = 20
    b = 10
    num1 = 10
    num2 = 20
    

    解析

    img

    在swap方法中,a、b的值进行交换,并不会影响到 num1、num2。因为,a、b中的值,只是从 num1、num2 的复制过来的。也就是说,a、b相当于num1、num2 的副本,副本的内容无论怎么修改,都不会影响到原件本身。

    通过上面例子,我们已经知道了一个方法不能修改一个基本数据类型的参数,而对象引用作为参数就不一样,请看 example2.

    example 2

        public static void main(String[] args) {
            int[] arr = { 1, 2, 3, 4, 5 };
            System.out.println(arr[0]);
            change(arr);
            System.out.println(arr[0]);
        }
    
        public static void change(int[] array) {
            // 将数组的第一个元素变为0
            array[0] = 0;
        }
    

    结果

    1
    0
    

    解析

    img

    array 被初始化 arr 的拷贝也就是一个对象的引用,也就是说 array 和 arr 指向的时同一个数组对象。 因此,外部对引用对象的改变会反映到所对应的对象上。

    通过 example2 我们已经看到,实现一个改变对象参数状态的方法并不是一件难事。理由很简单,方法得到的是对象引用的拷贝,对象引用及其他的拷贝同时引用同一个对象。

    很多程序设计语言(特别是,C++和Pascal)提供了两种参数传递的方式:值调用和引用调用。有些程序员(甚至本书的作者)认为Java程序设计语言对对象采用的是引用调用,实际上,这种理解是不对的。由于这种误解具有一定的普遍性,所以下面给出一个反例来详细地阐述一下这个问题。

    example 3

    public class Test {
    
        public static void main(String[] args) {
            // TODO Auto-generated method stub
            Student s1 = new Student("小张");
            Student s2 = new Student("小李");
            Test.swap(s1, s2);
            System.out.println("s1:" + s1.getName());
            System.out.println("s2:" + s2.getName());
        }
    
        public static void swap(Student x, Student y) {
            Student temp = x;
            x = y;
            y = temp;
            System.out.println("x:" + x.getName());
            System.out.println("y:" + y.getName());
        }
    }
    

    结果

    x:小李
    y:小张
    s1:小张
    s2:小李
    

    解析

    交换之前:

    img

    交换之后:

    img

    通过上面两张图可以很清晰的看出: 方法并没有改变存储在变量 s1 和 s2 中的对象引用。swap方法的参数x和y被初始化为两个对象引用的拷贝,这个方法交换的是这两个拷贝

    总结

    Java程序设计语言对对象采用的不是引用调用,实际上,对象引用是按值传递的。

    下面再总结一下Java中方法参数的使用情况:

    • 一个方法不能修改一个基本数据类型的参数(即数值型或布尔型》
    • 一个方法可以改变一个对象参数的状态。
    • 一个方法不能让对象参数引用一个新的对象。

    值传递和引用传递有什么区别

    值传递:指的是在方法调用时,传递的参数是按值的拷贝传递,传递的是值的拷贝,也就是说传递后就互不相关了。

    引用传递:指的是在方法调用时,传递的参数是按引用进行传递,其实传递的引用的地址,也就是变量所对应的内存空间的地址。传递的是值的引用,也就是说传递前和传递后都指向同一个引用(也就是同一个内存空间)。

    Java包

    JDK 中常用的包有哪些

    • java.lang:这个是系统的基础类;
    • java.io:这里面是所有输入输出有关的类,比如文件操作等;
    • java.nio:为了完善 io 包中的功能,提高 io 包中性能而写的一个新包;
    • java.net:这里面是与网络有关的类;
    • java.util:这个是系统辅助类,特别是集合类;
    • java.sql:这个是数据库操作的类。

    import java和javax有什么区别

    刚开始的时候 JavaAPI 所必需的包是 java 开头的包,javax 当时只是扩展 API 包来说使用。然而随着时间的推移,javax 逐渐的扩展成为 Java API 的组成部分。但是,将扩展从 javax 包移动到 java 包将是太麻烦了,最终会破坏一堆现有的代码。因此,最终决定 javax 包将成为标准API的一部分。

    所以,实际上java和javax没有区别。这都是一个名字。

    IO流

    java 中 IO 流分为几种?

    • 按照流的流向分,可以分为输入流和输出流;
    • 按照操作单元划分,可以划分为字节流和字符流;
    • 按照流的角色划分为节点流和处理流。

    Java Io流共涉及40多个类,这些类看上去很杂乱,但实际上很有规则,而且彼此之间存在非常紧密的联系, Java I0流的40多个类都是从如下4个抽象类基类中派生出来的。

    • InputStream/Reader: 所有的输入流的基类,前者是字节输入流,后者是字符输入流。
    • OutputStream/Writer: 所有输出流的基类,前者是字节输出流,后者是字符输出流。

    按操作方式分类结构图:

    IO-操作方式分类

    按操作对象分类结构图:

    IO-操作对象分类

    BIO,NIO,AIO 有什么区别?

    简答

    • BIO:Block IO 同步阻塞式 IO,就是我们平常使用的传统 IO,它的特点是模式简单使用方便,并发处理能力低。
    • NIO:Non IO 同步非阻塞 IO,是传统 IO 的升级,客户端和服务器端通过 Channel(通道)通讯,实现了多路复用。
    • AIO:Asynchronous IO 是 NIO 的升级,也叫 NIO2,实现了异步非堵塞 IO ,异步 IO 的操作基于事件和回调机制。

    详细回答

    • BIO (Blocking I/O): 同步阻塞I/O模式,数据的读取写入必须阻塞在一个线程内等待其完成。在活动连接数不是特别高(小于单机1000)的情况下,这种模型是比较不错的,可以让每一个连接专注于自己的 I/O 并且编程模型简单,也不用过多考虑系统的过载、限流等问题。线程池本身就是一个天然的漏斗,可以缓冲一些系统处理不了的连接或请求。但是,当面对十万甚至百万级连接的时候,传统的 BIO 模型是无能为力的。因此,我们需要一种更高效的 I/O 处理模型来应对更高的并发量。
    • NIO (New I/O): NIO是一种同步非阻塞的I/O模型,在Java 1.4 中引入了NIO框架,对应 java.nio 包,提供了 Channel , Selector,Buffer等抽象。NIO中的N可以理解为Non-blocking,不单纯是New。它支持面向缓冲的,基于通道的I/O操作方法。 NIO提供了与传统BIO模型中的 SocketServerSocket 相对应的 SocketChannelServerSocketChannel 两种不同的套接字通道实现,两种通道都支持阻塞和非阻塞两种模式。阻塞模式使用就像传统中的支持一样,比较简单,但是性能和可靠性都不好;非阻塞模式正好与之相反。对于低负载、低并发的应用程序,可以使用同步阻塞I/O来提升开发速率和更好的维护性;对于高负载、高并发的(网络)应用,应使用 NIO 的非阻塞模式来开发
    • AIO (Asynchronous I/O): AIO 也就是 NIO 2。在 Java 7 中引入了 NIO 的改进版 NIO 2,它是异步非阻塞的IO模型。异步 IO 是基于事件和回调机制实现的,也就是应用操作之后会直接返回,不会堵塞在那里,当后台处理完成,操作系统会通知相应的线程进行后续的操作。AIO 是异步IO的缩写,虽然 NIO 在网络操作中,提供了非阻塞的方法,但是 NIO 的 IO 行为还是同步的。对于 NIO 来说,我们的业务线程是在 IO 操作准备好时,得到通知,接着就由这个线程自行进行 IO 操作,IO操作本身是同步的。查阅网上相关资料,我发现就目前来说 AIO 的应用还不是很广泛,Netty 之前也尝试使用过 AIO,不过又放弃了。

    Files的常用方法都有哪些?

    • Files. exists():检测文件路径是否存在。
    • Files. createFile():创建文件。
    • Files. createDirectory():创建文件夹。
    • Files. delete():删除一个文件或目录。
    • Files. copy():复制文件。
    • Files. move():移动文件。
    • Files. size():查看文件个数。
    • Files. read():读取文件。
    • Files. write():写入文件。

    反射

    什么是反射机制?

    JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

    静态编译和动态编译

    • **静态编译:**在编译时确定类型,绑定对象
    • **动态编译:**运行时确定类型,绑定对象

    反射机制优缺点

    • 优点: 运行期类型的判断,动态加载类,提高代码灵活度。
    • 缺点: 性能瓶颈:反射相当于一系列解释操作,通知 JVM 要做的事情,性能比直接的java代码要慢很多。

    反射机制的应用场景有哪些?

    反射是框架设计的灵魂。

    在我们平时的项目开发过程中,基本上很少会直接使用到反射机制,但这不能说明反射机制没有用,实际上有很多设计、开发都与反射机制有关,例如模块化的开发,通过反射去调用对应的字节码;动态代理设计模式也采用了反射机制,还有我们日常使用的 Spring/Hibernate 等框架也大量使用到了反射机制。

    举例:①我们在使用JDBC连接数据库时使用Class.forName()通过反射加载数据库的驱动程序;②Spring框架也用到很多反射机制,最经典的就是xml的配置模式。Spring 通过 XML 配置模式装载 Bean 的过程:1) 将程序内所有 XML 或 Properties 配置文件加载入内存中; 2)Java类里面解析xml或properties里面的内容,得到对应实体类的字节码字符串以及相关的属性信息; 3)使用反射机制,根据这个字符串获得某个类的Class实例; 4)动态配置实例的属性

    Java获取反射的三种方法

    1.通过new对象实现反射机制 2.通过路径实现反射机制 3.通过类名实现反射机制

    public class Student {
        private int id;
        String name;
        protected boolean sex;
        public float score;
    }
    
    public class Get {
        //获取反射机制三种方式
        public static void main(String[] args) throws ClassNotFoundException {
            //方式一(通过建立对象)
            Student stu = new Student();
            Class classobj1 = stu.getClass();
            System.out.println(classobj1.getName());
            //方式二(所在通过路径-相对路径)
            Class classobj2 = Class.forName("fanshe.Student");
            System.out.println(classobj2.getName());
            //方式三(通过类名)
            Class classobj3 = Student.class;
            System.out.println(classobj3.getName());
        }
    }
    

    网络编程

    网络编程的面试题可以查看我的这篇文章重学TCP/IP协议和三次握手四次挥手,内容不仅包括TCP/IP协议和三次握手四次挥手的知识,还包括计算机网络体系结构,HTTP协议,get请求和post请求区别,session和cookie的区别等,欢迎大家阅读。

    常用API

    String相关

    字符型常量和字符串常量的区别

    1. 形式上: 字符常量是单引号引起的一个字符 字符串常量是双引号引起的若干个字符
    2. 含义上: 字符常量相当于一个整形值(ASCII值),可以参加表达式运算 字符串常量代表一个地址值(该字符串在内存中存放位置)
    3. 占内存大小 字符常量只占两个字节 字符串常量占若干个字节(至少一个字符结束标志)

    什么是字符串常量池?

    字符串常量池位于堆内存中,专门用来存储字符串常量,可以提高内存的使用率,避免开辟多块空间存储相同的字符串,在创建字符串时 JVM 会首先检查字符串常量池,如果该字符串已经存在池中,则返回它的引用,如果不存在,则实例化一个字符串放到池中,并返回其引用。

    String 是最基本的数据类型吗

    不是。Java 中的基本数据类型只有 8 个 :byte、short、int、long、float、double、char、boolean;除了基本类型(primitive type),剩下的都是引用类型(referencetype),Java 5 以后引入的枚举类型也算是一种比较特殊的引用类型。

    这是很基础的东西,但是很多初学者却容易忽视,Java 的 8 种基本数据类型中不包括 String,基本数据类型中用来描述文本数据的是 char,但是它只能表示单个字符,比如 ‘a’,‘好’ 之类的,如果要描述一段文本,就需要用多个 char 类型的变量,也就是一个 char 类型数组,比如“你好” 就是长度为2的数组 char[] chars = {‘你’,‘好’};

    但是使用数组过于麻烦,所以就有了 String,String 底层就是一个 char 类型的数组,只是使用的时候开发者不需要直接操作底层数组,用更加简便的方式即可完成对字符串的使用。

    String有哪些特性

    • 不变性:String 是只读字符串,是一个典型的 immutable 对象,对它进行任何操作,其实都是创建一个新的对象,再把引用指向该对象。不变模式的主要作用在于当一个对象需要被多线程共享并频繁访问时,可以保证数据的一致性。

    • 常量池优化:String 对象创建之后,会在字符串常量池中进行缓存,如果下次创建同样的对象时,会直接返回缓存的引用。

    • final:使用 final 来定义 String 类,表示 String 类不能被继承,提高了系统的安全性。

    String为什么是不可变的吗?

    简单来说就是String类利用了final修饰的char类型数组存储字符,源码如下图所以:

    /** The value is used for character storage. */
    private final char value[];
    

    String真的是不可变的吗?

    我觉得如果别人问这个问题的话,回答不可变就可以了。 下面只是给大家看两个有代表性的例子:

    1) String不可变但不代表引用不可以变

    String str = "Hello";
    str = str + " World";
    System.out.println("str=" + str);
    

    结果:

    str=Hello World
    

    解析:

    实际上,原来String的内容是不变的,只是str由原来指向"Hello"的内存地址转为指向"Hello World"的内存地址而已,也就是说多开辟了一块内存区域给"Hello World"字符串。

    2) 通过反射是可以修改所谓的“不可变”对象

    // 创建字符串"Hello World", 并赋给引用s
    String s = "Hello World";
    
    System.out.println("s = " + s); // Hello World
    
    // 获取String类中的value字段
    Field valueFieldOfString = String.class.getDeclaredField("value");
    
    // 改变value属性的访问权限
    valueFieldOfString.setAccessible(true);
    
    // 获取s对象上的value属性的值
    char[] value = (char[]) valueFieldOfString.get(s);
    
    // 改变value所引用的数组中的第5个字符
    value[5] = '_';
    
    System.out.println("s = " + s); // Hello_World
    

    结果:

    s = Hello World
    s = Hello_World
    

    解析:

    用反射可以访问私有成员, 然后反射出String对象中的value属性, 进而改变通过获得的value引用改变数组的结构。但是一般我们不会这么做,这里只是简单提一下有这个东西。

    是否可以继承 String 类

    String 类是 final 类,不可以被继承。

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

    不一样,因为内存的分配方式不一样。String str="i"的方式,java 虚拟机会将其分配到常量池中;而 String str=new String(“i”) 则会被分到堆内存中。

    String s = new String(“xyz”);创建了几个字符串对象

    两个对象,一个是静态区的"xyz",一个是用new创建在堆上的对象。

    String str1 = "hello"; //str1指向静态区
    String str2 = new String("hello");  //str2指向堆上的对象
    String str3 = "hello";
    String str4 = new String("hello");
    System.out.println(str1.equals(str2)); //true
    System.out.println(str2.equals(str4)); //true
    System.out.println(str1 == str3); //true
    System.out.println(str1 == str2); //false
    System.out.println(str2 == str4); //false
    System.out.println(str2 == "hello"); //false
    str2 = str1;
    System.out.println(str2 == "hello"); //true
    

    如何将字符串反转?

    使用 StringBuilder 或者 stringBuffer 的 reverse() 方法。

    示例代码:

    // StringBuffer reverse
    StringBuffer stringBuffer = new StringBuffer();
    stringBuffer. append("abcdefg");
    System. out. println(stringBuffer. reverse()); // gfedcba
    // StringBuilder reverse
    StringBuilder stringBuilder = new StringBuilder();
    stringBuilder. append("abcdefg");
    System. out. println(stringBuilder. reverse()); // gfedcba
    

    数组有没有 length()方法?String 有没有 length()方法

    数组没有 length()方法 ,有 length 的属性。String 有 length()方法。JavaScript中,获得字符串的长度是通过 length 属性得到的,这一点容易和 Java 混淆。

    String 类的常用方法都有那些?

    • indexOf():返回指定字符的索引。
    • charAt():返回指定索引处的字符。
    • replace():字符串替换。
    • trim():去除字符串两端空白。
    • split():分割字符串,返回一个分割后的字符串数组。
    • getBytes():返回字符串的 byte 类型数组。
    • length():返回字符串长度。
    • toLowerCase():将字符串转成小写字母。
    • toUpperCase():将字符串转成大写字符。
    • substring():截取字符串。
    • equals():字符串比较。

    在使用 HashMap 的时候,用 String 做 key 有什么好处?

    HashMap 内部实现是通过 key 的 hashcode 来确定 value 的存储位置,因为字符串是不可变的,所以当创建字符串时,它的 hashcode 被缓存下来,不需要再次计算,所以相比于其他对象更快。

    String和StringBuffer、StringBuilder的区别是什么?String为什么是不可变的

    可变性

    String类中使用字符数组保存字符串,private final char value[],所以string对象是不可变的。StringBuilder与StringBuffer都继承自AbstractStringBuilder类,在AbstractStringBuilder中也是使用字符数组保存字符串,char[] value,这两种对象都是可变的。

    线程安全性

    String中的对象是不可变的,也就可以理解为常量,线程安全。AbstractStringBuilder是StringBuilder与StringBuffer的公共父类,定义了一些字符串的基本操作,如expandCapacity、append、insert、indexOf等公共方法。StringBuffer对方法加了同步锁或者对调用的方法加了同步锁,所以是线程安全的。StringBuilder并没有对方法进行加同步锁,所以是非线程安全的。

    性能

    每次对String 类型进行改变的时候,都会生成一个新的String对象,然后将指针指向新的String 对象。StringBuffer每次都会对StringBuffer对象本身进行操作,而不是生成新的对象并改变对象引用。相同情况下使用StirngBuilder 相比使用StringBuffer 仅能获得10%~15% 左右的性能提升,但却要冒多线程不安全的风险。

    对于三者使用的总结

    如果要操作少量的数据用 = String

    单线程操作字符串缓冲区 下操作大量数据 = StringBuilder

    多线程操作字符串缓冲区 下操作大量数据 = StringBuffer

    Date相关

    包装类相关

    自动装箱与拆箱

    装箱:将基本类型用它们对应的引用类型包装起来;

    拆箱:将包装类型转换为基本数据类型;

    int 和 Integer 有什么区别

    Java 是一个近乎纯洁的面向对象编程语言,但是为了编程的方便还是引入了基本数据类型,但是为了能够将这些基本数据类型当成对象操作,Java 为每一个基本数据类型都引入了对应的包装类型(wrapper class),int 的包装类就是 Integer,从 Java 5 开始引入了自动装箱/拆箱机制,使得二者可以相互转换。

    Java 为每个原始类型提供了包装类型:

    原始类型: boolean,char,byte,short,int,long,float,double

    包装类型:Boolean,Character,Byte,Short,Integer,Long,Float,Double

    Integer a= 127 与 Integer b = 127相等吗

    对于对象引用类型:==比较的是对象的内存地址。
    对于基本数据类型:==比较的是值。

    如果整型字面量的值在-128到127之间,那么自动装箱时不会new新的Integer对象,而是直接引用常量池中的Integer对象,超过范围 a1==b1的结果是false

    public static void main(String[] args) {
        Integer a = new Integer(3);
        Integer b = 3;  // 将3自动装箱成Integer类型
        int c = 3;
        System.out.println(a == b); // false 两个引用没有引用同一对象
        System.out.println(a == c); // true a自动拆箱成int类型再和c比较
        System.out.println(b == c); // true
    
        Integer a1 = 128;
        Integer b1 = 128;
        System.out.println(a1 == b1); // false
    
        Integer a2 = 127;
        Integer b2 = 127;
        System.out.println(a2 == b2); // true
    }
    

    常用工具类库

    单元测试

    日志

    展开全文
  • 测试开发需要学习的知识结构

    万次阅读 多人点赞 2018-04-12 10:40:58
    努力成为一个优秀的测试开发从业者,加油!... - 假装在测试的回答 - 知乎白盒与黑盒测试什么区分1、黑盒测试 黑盒测试也称功能测试或数据驱动测试,它是在已知产品所应具有的功能,通过测试来检...

     努力成为一个优秀的测试开发从业者,加油!!!   

    目录

    一、白盒与黑盒测试什么区分

    1、黑盒测试

    2、白盒测试

    3、白盒测试&黑盒测试对比

    4、白盒测试&黑盒测试详细介绍

    黑盒测试

    白盒测试

    二、测试相关经验

    三、测试能力培养

    一、业务分析能力

    二、缺陷洞察能力

    三、团队协作能力

    四、专业技术能力

    五、逻辑思考能力

    六、问题解决能力

    七、沟通表达能力

    八、宏观把控能力


    借楼发个招聘信息:
    【2021 MEGQA-用户质量效能部校园提前批开始啦】
    工作职责:
    -负责百度核心产品的测试工作,如信息流、搜索、百度APP、小程序、好看视频、贴吧等
    -参与产品需求、系统设计和程序代码的评审工作并提出改进意见
    -评估项目质量风险并制定项目测试方案,设计并执行测试用例,跟踪定位产品软件中的缺陷或问题,保证项目质量和进度
    -根据产品和项目特点,提出合理的自动化解决方案,并负责产品线特色化的测试框架和测试工具,运用技术手段提升代码交付的质量和效率
    -参与互联网产品整个工程生产、发布过程中的技术创新,包括研发敏捷研发工具、线上监控系统、性能测试和监督工具等精确评估线上系统表现,以创新的工作模式提升产品的用户价值
    职位要求:
    -计算机相关专业,本科及以上学历
    -能熟练地应用以下一门或几门技术进行相关开发:C/C++/Java/object-c、Linux/Unix Shell、Perl/Python/PHP、JavaScript/Html/Ajax、MySql/Oracle及相关数据库技术等
    -具备快速的产品及业务学习能力,敏捷全面的逻辑思维能力
    -有责任心、敢于担当,工作积极主动,具备良好的团队合作精神,能融入多功能团队并与其他部门同事进行良好的沟通及合作
    -热爱互联网,对互联网相关业务或技术充满好奇及热情;在软件测试领域,对发现、分析及解决问题的工作有浓厚兴趣

    感兴趣的同学可以将简历投递至liujunping@baidu.com

     

    ========================================================================================

    一些视频链接:我这有一些软件测试的视频,你可以点开看看。

    转行互联网测试需要哪些技能? - 假装在测试的回答 - 知乎

    作为一名软件测试人员,有哪些网站是你应该多多关注的,哪些书籍是你必须要看的? - 假装在测试的回答 - 知乎

    一、白盒与黑盒测试什么区分

    1、黑盒测试

    黑盒测试也称功能测试或数据驱动测试,它是在已知产品所应具有的功能,通过测试来检测每个功能是否都能正常使用,在测试时,把程序看作一个不能打开的黑盆子,在完全不考虑程序内部结构和内部特性的情况下,测试者在程序接口进行测试,它只检查程序功能是否按照需求规格说明书的规定正常使用,程序是否能适当地接收输入数锯而产生正确的输出信息,并且保持外部信息(如数据库或文件)的完整性。黑盒测试方法主要有等价类划分、边值分析、因—果图、错误推测等,主要用于软件确认测试。 “黑盒”法着眼于程序外部结构、不考虑内部逻辑结构、针对软件界面和软件功能进行测试。“黑盒”法是穷举输入测试,只有把所有可能的输入都作为测试情况使用,才能以这种方法查出程序中所有的错误。实际上测试情况有无穷多个,人们不仅要测试所有合法的输入,而且还要对那些不合法但是可能的输入进行测试。

    2、白盒测试

    白盒测试也称结构测试或逻辑驱动测试,它是知道产品内部工作过程,可通过测试来检测产品内部动作是否按照规格说明书的规定正常进行,按照程序内部的结构测试程序,检验程序中的每条通路是否都有能按预定要求正确工作,而不顾它的功能,白盒测试的主要方法有逻辑驱动、基路测试等,主要用于软件验证。

    “白盒”法全面了解程序内部逻辑结构、对所有逻辑路径进行测试。“白盒”法是穷举路径测试。在使用这一方案时,测试者必须检查程序的内部结构,从检查程序的逻辑着手,得出测试数据。贯穿程序的独立路径数是天文数字。但即使每条路径都测试了仍然可能有错误。第一,穷举路径测试决不能查出程序违反了设计规范,即程序本身是个错误的程序。第二,穷举路径测试不可能查出程序中因遗漏路径而出错。第三,穷举路径测试可能发现不了一些与数据相关的错误。

    软件人员使用白盒测试方法,主要想对程序模块进行如下的检查:
    – 对程序模块的所有独立的执行路径至少测试一次;
    – 对所有的逻辑判定,取 “ 真 ” 与取 “ 假 ” 的两种情况都至少测试一次;
    – 在循环的边界和运行界限内执行循环体;
    – 测试内部数据结构的有效性,等。
    具体包含的逻辑覆盖有: – 语句覆盖 – 判定覆盖 – 条件覆盖 – 判定-条件覆盖 – 条件组合覆盖 – 路径覆盖。

    3、白盒测试&黑盒测试对比

    白盒测试技术 (White Box Testing) : 深入到代码一级的测试,使用这种技术发现问题最早,效果也是最好的。该技术主要的特征是测试对象进入了代码内部,根据开发人员对代码和对程序的熟悉程度,对有需要的部分进行在软件编码阶段,开发人员根据自己对代码的理解和接触所进行的软件测试叫做白盒测试。这一阶段测试以软件开发人员为主,在 JAVA 平台使用 Xunit 系列工具进行测试, Xunit 测试工具是类一级的测试工具对每一个类和该类的方法进行测试。

    黑盒测试技术( Black Box Testing ):黑盒测试的内容主要有以下几个方面,但是主要还是功能部分。主要是覆盖全部的功能,可以结合兼容,性能测试等方面进行,根据软件需求,设计文档,模拟客户场景随系统进行实际的测试,这种测试技术是使用最多的测试技术涵盖了测试的方方面面,可以考虑以下方面:

    1正确性 (Correctness) :计算结果,命名等方面

    2可用性 (Usability) :是否可以满足软件的需求说明。

    3边界条件 (Boundary Condition) :输入部分的边界值,就是使用一般书中说的等价类划分,试试最大最小和非法数据等等。

    4性能 (Performance) : 正常使用的时间内系统完成一个任务需要的时间,多人同时使用的时候响应时间在可以接受范围内。 J2EE 技术实现的系统在性能方面更是需要照顾的,一般原则是 3 秒以下接受, 3-5 秒可以接受, 5 秒以上就影响易用性了。如果在测试过程中发现性能问题,修复起来是非常艰难的,因为这常常意味着程序的算法不好,结构不好,或者设计有问题。因此在产品开发的开始阶段,就要考虑到软件的性能问题

    5压力测试 (Stress) : 多用户情况可以考虑使用压力测试工具,建议将压力和性能测试结合起来进行。如果有负载平衡的话还要在服务器端打开监测工具 , 查看服务器 CPU 使用率,内存占用情况,如果有必要可以模拟大量数据输入,对硬盘的影响等等信息。如果有必要的话必须进行性能优化 ( 软硬件都可以 ) 。这里的压力测试针对的是某几项功能。

    6错误恢复 (Error Recovery) :错误处理,页面数据验证,包括突然间断电,输入脏数据等。

    7安全性测试 (Security) :这个领域正在研究中,防火墙、补丁包、杀毒软件等的就不必说了,不过可以考虑。破坏性测试时任意看了一些资料后得知 , 这里面设计到的知识 内容可以写本书了 , 不是一两句可以说清的,特别是一些商务网站,或者跟钱有关,或者和公司秘密有关的 web 更是需要这方面的测试,在外国有一种专门干这一行的人叫安全顾问,可以审核代码,提出安全建议,出现紧急事件时的处理办法等,在国内没有听说哪里有专门搞安全技术测试的内容。

    4、白盒测试&黑盒测试详细介绍

    黑盒测试

      · 等价类划分方法
      · 边界值分析
      · 错误推测
      · 因果图方法
      · 判定表驱动分析方法
      · 正交实验设计方法:取正交的测试用例组合
      · 功能图分析方法
    1)等价类划分:
      把所有可能的输入数据,即程序的输入域划分成若干部分,然后从每一个子集中选取少数具有代表性的数据作为测试用例,该方法是一种重要的,常用的黑盒测试 用例设计方法。等价类划分可有两种不同的情况:有效等价类和无效等价类。
      有效等价类:对于程序的规格说明来说是合理的,有意义的输入数据构成的集合。利用有效等价类可检验程序是否实现了规格说明中所规定的功能和性能。
      无效等价类:与有效等价类的定义相反。
    2)边界值分析法:
      边界值分析方法是对等价类划分方法的补充。长期的测试 工作经验告诉我们,大量的错误是发生在输入或者输出范围的边界上,而不是发生在输入输出范围的内部,因此针对各种边界情况设计测试用例,可以查出更多的错误。
      使用边界值分析方法设计测试用例,首先应确定边界情况,通常输入和输出等价类的边界,就是应着重测试的边界情况,应当选取正好等于,刚刚大于或刚刚小于边界的值作为测试数据,而不是选取边界类中的典型值或任意值作为测试数据。
    3)错误推测法:
      基于经验和直觉推测程序中所有可能存在的各种错误,从而有针对性的设计测试用例的方法。
      列举出程序中所有可能有的错误和容易发生错误的特殊情况,根据他们选择测试用例。例如,在 单元测试时列出的许多在模块中常见的错误,以前产品测试中经常发现的错误等,这些就是经验的总结。还有,输入数据和输出数据为零的情况;输入表格为空格或者输入表格只有一行,这些都是容易发生错误的情况,可选这些情况下的例子作为测试用例。
    4)因果图方法:
      前面介绍的等价类划分方法和边界值分析方法,都是着重考虑输入条件,但未考虑输入条件之间的联系。考虑输入条件之间的相互组合,可能会产生一些新的情况,但要检查输入条件的组合意识一件容易的事情,因此必须考虑采用一种适合于描述对于多种条件的组合,相应产生多个动作的形式来考虑设计测试用例,这就需要利用因果图。
    因果图方法最终生成的是判定表,它适合于检查程序输入条件之间的各种组合情况。
    利用因果图生成测试用例的基本步骤:
      (1) 分析软件规格说明描述中, 那些是原因(即输入条件或输入条件的等价类),那些是结果(即输出条件), 并给每个原因和结果赋予一个标识符.
      (2) 分析软件规格说明描述中的语义.找出原因与结果之间, 原因与原因之间对应的关系. 根据这些关系,画出因果图.
      (3) 由于语法或环境限制, 有些原因与原因之间,原因与结果之间的组合情况不不可能出现. 为表明这些特殊情况, 在因果图上用一些记号表明约束或限制条件.
      (4) 把因果图转换为判定表.
      (5) 把判定表的每一列拿出来作为依据,设计测试用例.
      从因果图生成的测试用例(局部,组合关系下的)包括了所有输入数据的取TRUE与取FALSE的情况,构成的测试用例数目达到最少,且测试用例数目随输入数据数目的增加而线性地增加.
      前面因果图方法中已经用到了判定表.判定表(Decision Table)是分析和表达多逻辑条件下执行不同操作的情况下的工具.在程序设计发展的初期,判定表就已被当作编写程序的辅助工具了.由于它可以把复杂的逻辑关系和多种条件组合的情况表达得既具体又明确.
    5)判定表通常由四个部分组成.
      条件桩(Condition Stub):列出了问题得所有条件.通常认为列出得条件的次序无关紧要.
      动作桩(Action Stub):列出了问题规定可能采取的操作.这些操作的排列顺序没有约束.
      条件项(Condition Entry):列出针对它左列条件的取值.在所有可能情况下的真假值.
      动作项(Action Entry):列出在条件项的各种取值情况下应该采取的动作.
      规则:任何一个条件组合的特定取值及其相应要执行的操作.在判定表中贯穿条件项和动作项的一列就是一条规则.显然,判定表中列出多少组条件取值,也就有多少条规则,既条件项和动作项有多少列.
       判定表的建立步骤:(根据软件规格说明)
      ①确定规则的个数.假如有n个条件.每个条件有两个取值(0,1),故有 种规则.
      ②列出所有的条件桩和动作桩.
      ③填入条件项.
      ④填入动作项.等到初始判定表.
      ⑤简化.合并相似规则(相同动作)
      B. Beizer 指出了适合使用判定表设计测试用例的条件:
      ①规格说明以判定表形式给出,或很容易转换成判定表.
      ②条件的排列顺序不会也不影响执行哪些操作.
      ③规则的排列顺序不会也不影响执行哪些操作.
      ④每当某一规则的条件已经满足,并确定要执行的操作后,不必检验别的规则.
      ⑤如果某一规则得到满足要执行多个操作,这些操作的执行顺序无关紧要.

    白盒测试

    白盒测试的方法:总体上分为静态方法和动态方法两大类。

    静态分析是一种不通过执行程序而进行测试的技术。静态分析的关键功能是检查软件的表示和描述是否一致,没有冲突或者没有歧义。

    动态分析的主要特点是当软件系统在模拟的或真实的环境中执行之前、之中和之后 , 对软件系统行为的分析。动态分析包含了程序在受控的环境下使用特定的期望结果进行正式的运行。它显示了一个系统在检查状态下是正确还是不正确。在动态分析技术中,最重要的技术是路径和分支测试。下面要介绍的六种覆盖测试方法属于动态分析方法。

    本文介绍六种白盒子测试方法:(强度由低到高)语句覆盖、判定覆盖、条件覆盖、判定条件覆盖、条件组合覆盖、路径覆盖。

    1)所谓语句覆盖:就是设计若干个测试用例,运行被测程序,使得每一可执行语句至少执行一次。这里的“若干个”,意味着使用测试用例越少越好。语句覆盖率的公式可以表示如下:

    语句覆盖率=被评价到的语句数量/可执行的语句总数 x 100%

    2判定覆盖:使设计的测试用例保证程序中每个判断的每个取值分支(t or f)至少经历一次

    [优点]:判定覆盖具有比语句覆盖更强的测试能力,而且具有和语句覆盖一样的简单性,无需细分每个判定就可以得到测试用例。

    [缺点]:往往大部分的判定语句是由多个逻辑条件组合而成(如,判定语句中包含AND、OR、CASE),若仅仅判断其整个最终结果,而忽略每个条件的取值情况,必然会遗漏部分测试路径。

      例如:

      int a,b;

      if(a || b)

      执行语句1

      else

      执行语句2

    要达到这段程序的判断覆盖,我们采用测试用例:1)a = true , b = true ;2)a = flase, b = flase

    3条件覆盖:条件覆盖是指选择足够的测试用例,使得运行这些测试用例时,判定中每个条件的所有可能结果至少出现一次,但未必能覆盖全部分支

    条件覆盖要检查每个符合谓词的子表达式值为真和假两种情况,要独立衡量每个子表达式的结果,以确保每个子表达式的值为真和假两种情况都被测试到。

    4 判定条件覆盖:判定-条件覆盖就是设计足够的测试用例,使得判断中每个条件的所有可能取值至少执行一次,同时每个判断的所有可能判断结果至少执行,即要求各个判断的所有可能的条件取值组合至少执行一次。

    5) 条件组合覆盖:在白盒测试法中,选择足够的测试用例,使所有判定中各条件判断结果的所有组合至少出现一次,满足这种覆盖标准成为条件组合覆盖。

    6路径覆盖:是每条可能执行到的路径至少执行一次;

     说明:其中语句覆盖是一种最弱的覆盖,判定覆盖和条件覆盖比语句覆盖强,满足判定/条件覆盖标准的测试用例一定也满足判定覆盖、条件覆盖和语句覆盖,条件组合覆盖是除路径覆盖外最强的,路径覆盖也是一种比较强的覆盖,但未必考虑判定条件结果的组合,并不能代替条件覆盖和条件组合覆盖。

    举例:

    if A and B then Action1

    if C or D then Action2

    1)语句覆盖最弱,只需要让程序中的语句都执行一遍即可 。上例中只需设计测试用例使得A=true B=true C=true 即可。

    2)分支覆盖又称判定覆盖:使得程序中每个判断的取真分支和取假分支至少经历一次,即判断的真假均曾被满足。上例需要设计测试用例使其分别满足下列条件即可(1)A=true,B=true,C=true,D=false(2)A=true,B=false,C=false,D=false。

    3)条件覆盖:要使得每个判断中的每个条件的可能取值至少满足一次。上例中第一个判断应考虑到A=true,A=false,B=true,B=false第二个判断应考虑到C=true,C=false,D=true,D=false,所以上例中可以设计测试用例满足下列条件(1)A=true,B=true,C=true,D=true(2)A=false,B=false,C=false,D=false。

    4) 路径覆盖:要求覆盖程序中所有可能的路径。所以可以设计测试用例满足下列条件(1)A=true,B=true,C=true,D=true(2)A=false,B=false,C=false,D=false(3)A=true,B=true,C=false,D=false(4)A=false,B=false,C=true,D=true。

    二、测试相关经验

          测试流程方面我的组长是一位经验丰富的老测试了,到目前已经9年了,我在她的带领下,从最开始的分析需求开始,逐步地跟着项目走完整个测试流程,包括纯手工测试,包含了自动化的测试流程,包含了性能测试的测试流程,直至每一个测试报告的最终形成。使我完全理解了一个科学,正确,严谨,正规化的测试流程。

           测试方法方面我个人特别注重理论知识和实际操作相结合,在理论知识方面,我主要是购买一些书籍,从最基础的软件测试理论到各种各样的程序设计语言,再到自动化测试,包括Java语言的自动化测试,Python语言的自动化测试,到性能测试的各项性能指标的分析,数据分析都是我自己提供书籍上的知识来获得的,在淘宝上面有各种各样的书籍和视频教程,我基本上都看了个遍,到目前为止,我的各种学习资料用了1T的移动硬盘来装,书籍也有一百多本了,在实际操作方面,我主要向我的组长请教,她是因为女生,特别注重细节,当我有不懂得地方就去请教她,我会问她为什么要这么操作,然后我会对比理论和实际的区别,为什么有这种区别。就这样我就通过一个个的项目来夯实理论知识和实际操作,每一次做完项目我都会进行一个总结,自己学到了哪些新的技术和方法?遇到了哪些新的问题?以后再遇到怎么处理?

           新的知识补充方面:随着项目的不同,所运用的知识也不同,每一次学习不同的知识既是工作项目的需要,也是自己学习新知识的契机,比如说学习python语言,本来我们测试人员是不用写代码的,或者说可以用Java写,但是目前市面上都在用python语言来写自动化测试脚本,肯定是有它的道理的,那么我当时给自己的目标并不是仅仅为了满足写自动化脚本那么简单,我还想把python语言全部学会,我下定决心之后就立即着手执行,因为我本来就是开发出身,会代码,所有的语言都是相通的,都有变量,流程控制语句,和方法三大内容。JavaScript和Python都是弱类型,解释性的语言,所以在学习的时候我就在对比起来学习,很快学会了这门语言,所以我个人觉得,不管做什么,我们不仅仅要会用它,而且要知道它为什么这样用?最好是能够精通,对我们的测试工作是十分有利的。

           知识结构方面我们作为一个测试人员,不仅仅要做好本职工作,把自己的测试技术练好,而且还要一个广泛涉猎,对前台,后台,硬件知识,网络知识都应该去学习,对我们快速定位bug,提出有效针对性的修改硬件非常有好处,如果有条件的话,尽量向全栈发展。开发的发展方向是向深度和精度发展,而测试是一个向广度发展的岗位,需要不同的知识来融合,因为我们测试的是一个集成的,有多种技术融合而成的系统项目,就需要我们广泛涉猎和学习,所以从职业规划和寿命度上面来看,测试的工作也是非常的不错,所以不断的学习才是硬道理!

           团队的氛围方面我本人是军人出身,历来重视团结的重要性,所以和开发人员,测试人员,需求人员以及上级相处要从大局出发,我们的每一个人员都是一个项目不可或缺的一份子,必须团结起来,才能为最后产品的顺利交付打好基础条件,所以同事之间的相处是最需要拿捏分寸的,特别是开发人员,人和人都是相互的,只要讲道理,相信别人是会理解的,总之一句话:从整个项目的大局出发,把工作做好。

           回首测试经历,我总结了以下几点:

           1.不断学习,不能丧失对新知识学习的渴望,对旧的知识形成体系,夯实基础,测试理论知识基本上这么多年以来没有变过,主要是一些方法和工具的改变和升级,广泛涉猎相关知识,为测试工作服务;

           2.搞好内部团结,建立起亲密的同事关系,不仅是对个人社交能力还是对自己的工作上的能力都是一个提升,都是百利而无一害的!

    三、测试能力培养

    一、业务分析能力

    1.分析整体业务流程

    不了解整个公司的业务,根本就没办法进行测试

    2.分析被测业务数据

    了解整个业务里面所需的数据有哪些?哪些是需要用户提供的?哪些是自己提供的?有哪些可以是假数据?有哪些必须是真数据?添加数据的时候可以用哪个库?

    明白了整个软件的数据库架构,才能知道哪一个数据是从哪一个表里头带出来的,它的逻辑是什么,有没有连带关系。

    3.分析被测系统架构

    用什么语言开发的?用的是什么服务器?测试它的话需要用什么样的环境进行测试?整体的测试环境是什么样的?

    如果缺少了,需要进行环境搭建,架构搭建。一般去一家新公司之后,架构是搭建好的,了解它即可,熟悉之前的这些老员工们使用什么样的架构去做的。

    4.分析被测业务模块

    整个软件有哪些模块,比如说首页面、注册页面、登录页面、会员页面、商品详情页面、优惠券页面等等

    明白有多少个模块需要测试,每个模块之间的连带关系,进而怎样进行人员分工

    5.分析测试所需资源

    我需要几台计算机,需要几部手机,手机需要什么样的系统,什么样的型号。

    比如测一个网站的性能的时候,电脑的配置达不到测试并发5000人的标准,要么升级电脑的硬件配置,要么多机联合,多机联合时需要几台电脑,都需要提前筹划。

    6.分析测试完成目标

    我的性能目标是什么样的?我的功能目标是什么样的?我要上线达到的上线标准是什么样的?

    性能目标,比如我要达到并发5000人的时候,CPU占用率不能高于70%,内存占用率不能高于60%,响应时间不能超过5秒

    功能目标,比如整体的业务流程都跑通,所有的分支流程都没有问题,所有的接口都能够互相调用,整体的UI界面没有问题,兼容性没有问题等

    把这些问题都弄清楚,测试的思路会非常的清晰

    二、缺陷洞察能力

    1.一般缺陷的发现能力

    至少你要满足一般缺陷的发现能力,这个是最基本的,如果要连最简单的一般的缺陷都发现不了的话,别说优秀测试工程师了,你说你是测试我都不信

    2.隐性问题的发现能力

    在软件的测试过程当中有一些缺陷藏的比较深,有的是性能方面的问题,有的是功能方面的问题,它需要有一些设定特定的条件的情况下才会出现这样的问题。

    比如说买双鞋必须选择的是什么品牌,必须选择是红颜色,必须选择44号,而且必须选择用特定的支付方式才会出现这样的bug的时候,那么这种就属于特别隐性的bug,对于这样的问题的发现能力一定要比别人更强,要找到一些别人可能发现不了的bug

    3.发现连带问题的能力

    当发现了一个缺陷之后,能够想到通过这个缺陷可能会引发其他哪个地方出现问题,这就叫做连带的问题。而不是说发现这一个bug之后提了这一个就算完了,一定要有一个察觉,可能其他地方也存在这样的问题。

    4.发现问题隐患的能力

    有些软件里边可能有一些操作模块,或者是代码写的接口,表面上没有什么问题,但是它是有隐患的,比如说这个接口写的不稳定,当他传的数据有一些问题的时候,可能它最后返回的结果就是报错就是报404或者报乱码。

    5.尽早发现问题的能力

    如果你只能停留在界面级别的话,那你根本就没有办法达到尽早发现问题的这个能力

    你必须要等到前端人员把每个界面都做好了之后才能进入测试,而我能比你早一个月进入测试了,然后我比你结束测试时间快一个月,而你又比我晚一个月,那么咱俩的薪资一下就拉开了

    6.发现问题根源的能力

    需要知道这个缺陷它到底是由什么原因产生的,是属于什么类型的缺陷,是ui前端人员做的问题,还是后台接口人员做的问题?

    不仅要找到这个bug,还要知道这个bug产生的原因,这样的测试人员是非常棒的,而且很是受人尊敬,提bug的方式也就不一样了

    三、团队协作能力

    1.合理进行人员分工

    合理的进行人员分工是提高效率的重要保证

    2.协助组员解决问题

    比如说测试在赶进度,或者这个软件项目的质量把控是一个团队来把控的,协助组员解决问题就显得尤为关键

    3.配合完成测试任务

    一个团队里边的人员分工,他们的任务都是不一样的,这就是咱们说的配合。你的东西做完了,要轮到我了,我的性能测完了之后该轮到你了,所以整个的一个流程下来之后,大家应该是各司其职,配合得非常紧密的一个过程

    4.配合开发重现缺陷

    我给你提bug,你改我的bug,咱们的目的只有一个,就是让这个软件变得更好,所以在这样的情况下,咱们就一定要配合开发

    5.督促项目整体进度

    既然是一个团队协作的过程,就一定要互相的去督促对方,包括督促开发去改bug,因为开发人员他们有时候工作很忙,他们不知道要先改哪些问题,要后改哪些问题,但是往往有一些缺陷,它影响了测试的这个时间,影响了测试的进度,那么这个时候就需要测试员去督促开发人员,让他尽快的去解决你棘手的问题。这个东西能够提高咱们的测试效率

    6.出现问题勇于承担

    愿意背锅的最后都成为了领导,不愿意背锅的最后依然是员工

    四、专业技术能力

    1.掌握测试基础知识

    基础知识就是根基,根基打好了,你才能够更有效地往后期发展,也就是为了以后的学习做一个铺垫。如果根基都没打好,功能测试不会,就想直接学性能,那性能是做不好的

    2.娴熟运用测试工具

    熟悉工具和熟练使用工具完全是两个概念,熟悉工具基本上等同于不会,遇到过很多简历上写会使用什么什么工具,都没有实际能力。比如loadrunner只会一个简单的录制,增强一下脚本,觉得会用了,那知识会用了1/5,其他4/5 都不会。

    3.了解工具操作原理

    它是怎么样给服务器发送请求的,是用什么样的方式去发送请的,是用什么样的方式去监控的,它的操作原理是什么样的,咱们要把这件事情搞清楚,这样的话能有助于更好的去使用这些东西。包括一些请求的协议,每个协议代表什么意思,它是用来干什么的。

    4.自主完成测试任务

    一定要能够自己完成一个独立的内容,独立的工作,这件事情领导你交给我好了,放心我能给你搞定,要的是这样的人

    5.找出问题出现原因

    找出缺陷的时候,不仅要看它的表面,还要看它的本质

    6.提供问题解决方案

    发现问题不是能力,发现问题并提出解决方案才是真的能力

    7.提供完整测试报告

    测试报告能够说明你表达的清不清楚?领导能不能看懂?还有就是能不能够把你整个测试的过程给它梳理得非常详细,人家能够通过你的报告,能够了解到整个的项目的情况,而不是只了解一个片面的情况

    8.了解相关技术领域

    触类旁通

    五、逻辑思考能力

    1.判断逻辑的正确性

    面试官也经常会给测试人去出一些逻辑题,逻辑题能够分析出来你这个人思维有没有?活跃不活跃?还有他的维度,包括他想的问题的全面性,都能够判断得出来。

    比如说去买一样商品,它的里边逻辑就会经常会出现很多问题,比如说它的会员的级别,什么样的级别去买什么样的商品,它的价格不一样,什么情况下会给优惠券,什么样的情况下不给优惠券?达到多少钱的情况下才能够使用优惠券?如果说这里边的逻辑出现了问题的话,那么整个的业务不用再测了

    2.对可行性逻辑分析

    要去测一个网站的逻辑的时候,一定要先思考这一个业务流程可能会涉及到哪些逻辑,这些逻辑哪些是可行的,有些是正向逻辑,有些是逆向逻辑,都要考虑全面,而不是说只是把正向的逻辑测试全面了,逆向逻辑不考虑。其实往往更容易出错的地方就是逆向逻辑

    3.思维导图梳理思路

    思维导图工具能够起到什么作用,能够让你更有效的进行测试,能够让你的思路更清晰

    4.站在客观角度思考

    去测试的时候,不要仅仅只是站在测试人员的角度上去对整个网站进行测试,还更多的要站在用户的角度,要替用户考虑

    六、问题解决能力

    1.技术上的问题

    把自己的个人能力提升起来,多跟别人虚心请教,多去自己想办法解决问题

    2.工作中的问题

    在任何的企业里边去工作,肯定会遇到一些工作当中的一些不愉快的事情,而不是什么事情都会让你很顺心。所以要去处理工作上的一些不顺心的事情,不要把它带到你的工作上,或者是你的生活上,尽可能的去跟别人沟通,去解决这个工作上遇到的麻烦

    3.同事间的问题

    在工作当中可能会涉及到跟开发人员的沟通,跟产品人员的沟通,跟ui人员的沟通,跟这三方的人员去沟通的时候,就要用不同的沟通方式

    4.领导层的问题

    如果你觉得你的领导不好,或者说你觉得对你的领导一些建议,不要的去跟同事之间去说他坏话或者怎么样的,领导需要的是解决问题的人,而不是制造问题的人

    七、沟通表达能力

    1.和技术人员的沟通

    跟开发人员阐述缺陷时要简洁明了、清晰易懂。当发现严重缺陷时,也不要大惊小怪,要站在开发人员的角度思考如何解决问题。而不是踩在开发头上,炫耀自己发现问题的能力。

    2.和产品人员的沟通

    当对产品提出意见时,要站在用户的角度去说明自己的想法,而不要主观认为不好而要求产品进行修改。

    3.和上级领导的沟通

    跟领导沟通时要有大局观,不能只考虑自己部门的情况。并且与领导沟通时,尽量直奔主题,不要拐弯抹角,当与领导意见不一致时,也不要直接反驳,应该先给予认可,再阐述自己的想法。

    4.在集体会议中沟通

    在集体会议中不要一味的突出自己的个人能力,不要当话痨,也不要默默无闻。适当的提出一些自己的见解,有助于让大家更加重视你的存在。切记不要在多人会议中,去指责别人和推卸问题。各个部门的同事,都要面子~

    5.与下级员工的沟通

    与下级沟通时不要摆高姿态,不要让下级产生畏惧感,应该更多的为下级解决问题。服务好部门的同事,才能更好的产生凝聚力。

    八、宏观把控能力

    1.有效控制测试时间

    测试周期的时间控制,应当采取多种方法去衡量,例如人员能力,人员数量,项目复杂程度,同类项目的测试经验等多方面去衡量。

    2.有效控制测试成本

    测试成本指的是人员成本跟时间成本,不要浪费每个人的时间跟劳动力,要让每个人充分发挥最大的价值。

    3.有效制定测试计划

    测试计划对于一个项目是核心关键,它的存在为了让测试进行中有依据可查。所以测试计划,一定要切合实际情况,要经过思考和衡量最后得出计划安排。

    4.有效控制组员情绪

    组员的情绪可以直接影响测试进度跟测试的质量,当有组员出现思想问题时,应当及时沟通,采取一些必要的措施去解决问题。而不能装看不见。

    5.有效进行风险评估

    任何项目在进行期间都存在许多潜在的风险,例如,人员离职,生病请假,业务变更,需求变更,服务器或其他组件故障等。应当提前做出相应的解决方案,以免到时候手忙脚乱。

    6.有效控制测试方向

    测试的方向是指测试的目标和测试的范围,很多项目的测试是有针对性的,例如性能测试,所以在测试中,一定要随时清楚测试的目标和目的是什么,以免把时间浪费在无关紧要的业务上。

    展开全文
  • 浦发银行 信息科技岗 大数据方向 面经

    万次阅读 多人点赞 2018-08-09 23:00:31
    其他童鞋可以安心去其他公司继续面试, (后来发体检通知的时候, 我都忘记自己面过浦发) 1 大家的面经 1.1 浦发银行总行(上海)大数据岗8月6号面经 https://www.nowcoder.com/discuss/91911 我是8月6号12:30...

    浦发银行总行信息科技部(大数据方向)面试

    0绪论

    0.1 面试

    2018.8.6日面试了浦发银行信息科技岗,想写一个面经,发现大家都说的差不多了(面试流程较为固定),所以总结一下大家的面经(主要来自牛客网: https://www.nowcoder.com/search?type=post&query=%E6%B5%A6%E5%8F%91 ),为后来人提供个参考(明年应该变化不大)。

    面试主要分为三个部分:

    1. 即兴演讲(结构化面试 3面试官对6个学生)、
    2. 上机测试、
    3. 专业面试(3对1)。

    这三个顺序不固定,哪里面试官有空位 工作人员就先安排大家面哪一个部分。

    大家应该重点参考一下“结构化面试”的题目,提前排练一下,提前想一下“如果是我来回答这个问题,我该怎么答?” “别人把我想说的都说过了,怎么办?”,提前准备一下“固定套路、万能句式”,毕竟做编程的同学在这方面都不是特别强。(包括我 (┬_┬)

    0.2 招聘时间流程 参考

    • 2019届应届生参加 上海总部信息科技提前批,2018年8月6日面试,
    • 10月16日体检通知,
    • 11月21日背调邮件,
    • 11月30日给的offer邮件.

    浦发比较传统且谨慎,因此求职总流程比较慢,铁心去浦发的童鞋一定注意保留自己的三方,不要提前签了别家; 其他童鞋可以安心去其他公司继续面试, (后来发体检通知的时候, 我都快忘记自己面过浦发)

    1 大家的面经

    1.1 浦发银行总行(上海)大数据岗8月6号面经

    https://www.nowcoder.com/discuss/91911

    我是8月6号12:30的场次,面试的是大数据岗。面试一共三部分:综合面,技术面,机试,不分先后顺序,在2楼大厅等着工作人员叫名字,叫到哪里就去哪里参加面试。

    一、综合面

    综合面也就是群面,六个人一组,一共三个面试官。每个人进去抽题,每组有两道题目,抽到以后两分钟时间阅读材料,阅读完以后每个人三分钟时间阐述自己的观点。我当时抽到的题目是“长租公寓行业是否值得投资”,当时组里还有一道题目是关于“高考选择志愿”

    的问题,因为不是我所抽到的题目,所以没有额外留意。每个人三分钟演讲结束后,面试官会单独问问题,有的面试小组是每个人都被问到了,但我在的小组里我和另外一个男生没有被单独问问题,有可能是我三分钟演讲表现不好或者其他原因。后来面试官最后提了一道抢答题,当时考虑到自己没有被单独问问题,所以就抓紧抢了抢答题,但抢答嘛,没有时间考虑答案,所以回答也不是很好,群面就这样结束了。

    二、机试

    在大厅等候的时候工作人员会给你讲哪些岗位是必须要参加机试的,哪些岗位是不必须参加的但若你选择参加会给加分,所以基本上所有的人都会选择机试。机试题目都很简单一共三道题目:①输入一个数字要求输出该数字各个位上偶数的和,如输入5584,输出12。②输入一组数N和数字b ,求出该组数字中能被b 整除的个数。如输入1 2 3 4 5 6和 2,结果输出为3。③求N阶楼梯共有多少种上楼方式,每次只能上1个或2个台阶。编译环境只有java和c和c++,其他语言写的没办法现场编译,但工作人员说仍然提交,他们后再后台看你写的程序。我是用python写的。

    三、专业面试

    专业面试是让我觉得最无法描述的面试,仍然是工作人员喊到你的名字后去面试的地方等,三个面试官。当时我等的时候我前面有四个人,一个哈工大研究生,一个西安交大研究生,一个武汉大学的,还有一个美国回来的硕士生。工作人员说每个人面试时间10到15分钟,但我前面的几个都基本上15分钟,有的还有20分钟的。当时我在等的时候,他们每出来一个也和交流了一下面试官问了哪些问题,他们说自我介绍,针对自我介绍问了一些项目和算法问题。所以我自认为准备还是不错的。

    等我进去以后,面试官同样让我先自我介绍,我当时介绍了一下我是哪个大学什么专业的硕士,然后介绍了一下我会哪些机器学习算法,python编程,hive环境下sql 脚本开发,讲了一个我用逻辑回归和随机森林做的一个项目,最后讲了一下我上一份互联网公司的实习做的东西,在公司主要负责的事情。

    我觉得我的自我介绍还可以,只要想问应该能挖出来很多技术问题可以问。但面试官没有问我一个技术问题,从头到尾也只有一个面试官在问我,我自我介绍结束以后的问题:①我本科哪个学校的,学的什么专业(我本科普通一本非211),②说我硕士专业是控制,和大数据不对口。我解释了一下,虽然我是控制专业,但我导师是机器学习方向的,所以我做的也都是机器学习方向的东西。③问我不是计算机专业的,是不是对计算机编程的东西都不是很懂?(我当时也是一脸懵逼)我解释了一下说我可能做开发比不过计算机的学生,但我基本的东西都会,包括数据结构,操作系统的话Linux 基本指令都会,只不过编程语言是python不是java或者C++。④问我研一都在干什么?(我回答研一主要是上课和看论文)接着问我上什么课(我回答了模式识别,最优化方法,矩阵理论等)⑤接下来面试官就总结了一下,大概意思就是:我的专业不对口,虽然我说了我这些东西也做了不少实际的项目和事情,但给他们的感觉就是我学的很杂,乱七八糟的,让他们无从下手问我问题,感觉我不太符合大数据岗,还有一个就是他们觉得我会的这些东西都是我自学的,因为我的专业不对口(我也是一脸懵,即使计算机的学生,很多东西也不是老师上课教的呀,都是自己自学)

    总之,技术面就这样结束了,我具体多长时间没看表,但大概七八分钟吧,绝对不到十分钟。回来以后我也在反思技术面哪里出了问题。各种原因吧,肯定有我自身的原因。也有可能我前面都是双985都是很优秀的人,到我这面试官压根不想面我吧,不想深入交流。也有可能面试官对我学历和专业不满意(本科普通一本,硕士上海这边的211)

    总之,感觉找工作很随缘吧,我还幻想如果分到别的技术面小组说不定面试官会问我几个技术问题呢,现在也看开了,反正就水了水浦发,炮灰一把呗。

    1.2 浦发面经

    作者:白夏是小白
    链接:https://www.nowcoder.com/discuss/91866
    来源:牛客网

    我投的是总行信息科技部,面试主要分为三个部分:即兴演讲、上机测试、结构化面试。在武汉面试的,从上午十二点左右到武汉分行,到了下午六点多才走,等待面试等得心急如焚。HR小姐姐们十分贴心了,给又饿又焦急的我们买了面包牛奶,笔芯:)

    即兴演讲

    即兴演讲六个人一组,每个人都有一个序号,然后面试的时候一共有三个面试官。进去之后每个人抽一个题目,两分钟看题三分钟回答。这个回答次序是自定的,虽然说第一个举手回答有一定好处,但是一定要思路想清楚描述想清楚了再回答啊QAQ,大概主要是考察表达能力吧,我抢第一个结果回答得巨烂ORZ
    我的题目是说学校决定把什么校车超市之类的地方交由学生管辖,有人认为这会让学生重商轻学,然后问你的看法。
    六个人都回答完之后面试官会提一个问题让六个人回答,我们的问题是“大学里得分最高的一门课是什么?为什么能拿这么高的分?”,然后再抽几个人问了问题,面试官特地问了我一个“你是本科生?”的问题,觉得本科生仿佛受到歧视。

    上机测试

    上机测试是三道巨简单的题目,大概每一个几行代码吧。
    我的三个题目是:
    字符串反转
    数列求和
    字符串缩写
    (悄咪咪说一句,还可以看到大家的做题状态和排名,而且好像是手改,不是很懂)

    结构化面试

    结构化面试就是正常的面试,大概一个人十分钟左右的样子,人多,面试官少,等得生无可恋。三个面试官对一个人,一个主面试官问一些基础问题,然后旁边两个面试官有针对性的问问题,应该一个是问语言,一个是问数据库。
    一开始先自我介绍,然后开始问专业问题,好像面试官手上有一个记录,问一个问题,你说会他做一个记号,说不会或者停顿沉默一会儿就会划掉下一个问题(时间很紧不能迟疑吖)。
    结构化面试大概是整个面试流程中最体现专业的地方了吧可是我并没有感觉到很专业。我在网申的时候在简历上写了一句觉得银行的工作压力比互联网公司小,然后面试的时候特地问了我一句,“你确定吗”,搞得我很虚,我说我接受不了长期熬夜,总觉得会因为这个被毙掉ORZ

    总结
    整个过程下来,我觉得面试银行本科生毫无竞争力,一片全是研究生大佬;而且银行的面试让人捉摸不定,不知道他们到底想要什么样的人,可能比较需要全方面发展,可是技术的话就比较一言难尽。但是整个过程下来就没什么压力,人比较放松,虽然之后越想越凉凉吧emm
    据说浦发结果短则一个月多则两三个月才出来QAQ可能是并不想招人!

    1.3 浦发银行大数据创新岗上海打卡

    作者:明媚_
    链接:https://www.nowcoder.com/discuss/91675
    来源:牛客网

    面试分为三部分

    第一部分 综合面试

    6-7个人抽材料,阅读两分钟,表述三分钟,目前了解到的题:央行发布撤销某些地区的地铁修建资格,问认为这些地区是否该修建/积极废人/阅读习惯/中国是圆珠笔产量大国,核心技术掌握在别的国家/人工智能对银行的影响/无纸化阅读

    第二部分 专业面试

    首先进行自我介绍,根据自我介绍进行提问,确实重视项目,项目问了很久,别的没怎么问,感觉面试官并不专业。除项目问题,问了为什么这么多银行选择来浦发/你的职业规划/最近浦发上一款新产品你知道吗/对互联网有热情吗

    第三部分 上机考试(只有开发和测试岗需要,别的岗可选)

    我做的是以下三道题(开发语言不限)
    1 N的阶乘
    2 输入十个数,最大数和最后一个数交换,最小树和第一个数交换
    3 猴子吃桃子(经典问题,自行百度)

    求好运,攒人品啦?

    1.4 浦发总行信息岗校招面经(上海)

    作者:疯狂求offer
    链接:https://www.nowcoder.com/discuss/91174
    来源:牛客网

    之前也看了不少牛客上的笔经面经,感觉收获很多,昨天(8.5)面了浦发,趁着还有印象写个面筋回馈牛客,顺便攒攒秋招RP~

    我面的系统开发岗,面试时间是8.5中午12:30,当时提前一个多小时坐地铁过去的。结果从12号线虹梅路下来后导航导偏了,绕着附近的科技园转了一圈,经过好心的保安大叔指点后才知道莲花路1688号在哪儿_(:з」∠)_。浦发漕河泾这边的信息园区不是很大,走进楼里感觉环境挺好的,干净整洁,走廊里铺有地毯很舒服。本来以为会迟到,结果到签到处的时候发现前面好多人……排队都要绕着弯儿,目测下午场有接近100个人。由于是中午,当时我还听见HR小姐姐对上午场的同学们说如果没有面试完可以领饭票去一楼食堂免费吃饭,顿时就还挺有好感的,毕竟能为面试者们着想。在签到处会扫描身份证,拿一张打印有自己名字的纸(当作铭牌用)和一张小纸条。小纸条上写的是面试的三个环节:综合面试、专业面试和上机考试,然后就坐在等候区等待HR小姐姐叫号了。等待过程略去不表。

    专业面

    我首先抽到的是专业面试,大概进行了二十多分钟。有三位面试官,有两个感觉像是管理层,大概五十多岁,还有一个大概三十多岁。首先是自我介绍,表明了一下为什么想去浦发。首先是较年轻的面试官提问,开始问了项目,由于项目是做并行计算的,就让我讲讲设计和实现细节。然后问了数据库,增查删改等SQL命令,还问用过哪些数据库(项目中的),其实我做的项目没用数据库_(:з」∠),就略尴尬,但也如实回答了,为了挽回点气氛我就说了数据库事务的四大特性(ACID)和例子,然后他就接着问原子性的实际应用场景,我再举了个例子但是感觉好像那个面试官不太满意。接着问有没有做过socket之类的网络编程,我说没有……由于项目是在Linux集群下实现的,好像他们不太懂,就解释了一番,感觉他们好像还是没懂(:з」∠),然后就问了Linux下的常用命令。由于我不是计算机专业的,就问我有没有上过数据结构与算法的课,然后问了常用的排序算法以及口述快排的实现思路。接着其中一个面试官就问我本科研究生阶段都上过什么课程,然后问原专业做的挺好的为什么想转行来银行,我就商业互吹了一波。坐中间的那个大佬突然冷不丁说,你导师知道你转行来银行面试吗,导师同意吗。我懵逼了1s后就说导师很好不会限制学生云云,大佬也没继续问。面试官们貌似对做的项目挺感兴趣,又让我讲并行是怎么实现的,有啥优化的地方。最后大佬说有啥想问的,我突然犯二就问您在浦发一天的工作是怎么样的,这时候轮到大佬一愣(:з」∠)……估计他心想这小伙子胆儿够肥啊。然后面试官们就说了一通,听下来了解到他们都是管理层的,大佬惹不起惹不起(:з」∠)_。然后又问我还有啥问题,我说没有了,于是专业面结束。出来的时候看了看表,有二十多分钟,听候场区的几个人说他们都很快就十多分钟,我估计是因为自己非科班的缘故,被抓着一通提问。

    结构化面试

    接着又是漫长的等待,这次我抽到了综合面试(群面)。技术岗还有群面我也是有点懵的,心想待会儿说的时候有条理一些就行。群面形式就是每个人2分钟阅读一份材料,然后3分钟阐述观点。我抽到的是网络成瘾这块儿。思路还是不错的,有条理分点阐述了,但是我以为时间很紧就语速很快地说了,不知道面试官听明白了没有,事后感觉这块儿太可惜了语速应该平稳一点,因为我后面的小伙伴们都是慢悠悠地说完的,面试官也没把他们怎么着_(:з」∠)_。接着就是提问环节,没啥好说的。但是其中一个面试官就点出为啥不穿正装,我就很尴尬(之前是谁说银行技术岗不穿正装也OK的啊喂)……后来解释说得体的衣服就行了,也没说啥。大概三十分钟左右群面就结束了,又回到排队叫号环节。

    上机考试

    上机考试的地方大概有三四十台机子,很多人在做题,做完签字就可以走。不得不吐槽一下那个OJ系统和本地IDE是真的难用,一开始很不顺手。OJ上支持的语言有Java、C、C++,没有的可以用伪代码,后面会人工判题给分。题目很简单有三道题,分段函数实现、两个字符串查重、凯撒密码,分值分别是40,40,20。有一题我在本地调试成功但是在OJ上死活都编译不通过,很迷,但我也索性提交了,一切随缘。这个OJ系统还有调试10s内不能提交这种莫名其妙的设定,搞得现场很多人出错。据说除了大数据岗位其他都需要上机考试,但是我感觉几乎所有都去上机了。上机结束后我就坐地铁回学校了,这一天不知道怎么的肚子很不舒服,体验了好几次浦发的洗手间(还挺干净的,一点异味都没有)(:з」∠)

    整个流程很长,我从12:30一直到17:30左右才结束。总结下来感觉银行类的面试很注重数据库及相关实现,如果有相关经历是最好不过了。

    1.5 【浦发银行】信息科技岗(大数据创新岗)8.6日上海总行面经

    作者:爱吃水果的鱼
    链接:https://www.nowcoder.com/discuss/91147
    来源:牛客网

    楼主是中午12:30场次的,因为从上海其他地方坐地铁到漕河泾开发区地铁站,没有吃中午饭,问了下门卫,说可以在食堂吃,25块钱,可支付宝,酸奶水果饮料3选2,菜任意吃。
    具体请见图片,菜色一般般吧,还稍稍有点贵,不过我觉得他们银行工作人员是有饭补的,哈哈哈
    具体流程如下,面试等候区在2楼,电梯出来右手边可以看到指示牌,往厕所那个方向走,就能看到一堆人,先排队,打印自己的名牌,然后等。等着被叫去上机考试(c/c++,JAVA可以测试运行,提交的步骤为提交—>可以本地复制代码---->最下方测试运行----->提交,可以看到自己的代码是否正确),综合面试,专业面试,三者顺序不一定按照所说顺序,哪里有空就把你安排到哪里。
    面试时间大部分都在等候,做完机试在等候区等候,专业面试完去等候区等候,综合面试完就可以走了,很奇怪的是我的专业面试只有5分钟左右,可能说自己不了解数据库,和面试岗位不太匹配吧,23333,具体面经看下图!

    这里写图片描述

    1.6 热乎乎的浦发总行8月6日面筋!

    作者:上海伊泽瑞尔
    链接:https://www.nowcoder.com/discuss/91095
    来源:牛客网

    本人秋招第一次大型面试,打卡攒人品。

    浦发银行总行信息科技部(需求设计方向)面试
    时间:8月6日12:30-16:00

    面试在总行,离学校比较远,所以我提前两小时出发,到的时候前台小姐姐给了我一张餐券,幸福!!食堂伙食还不错!
    候场的candidate黑压压的一片,我问了下工作人员,说这三天在上海面试的总行信科的就有700多人,可见竞争多激烈(大家都开玩笑地说难道笔试不刷人?)
    到点后有工作人员来讲规则,面试分为三部分:综合面试、专业面试和机考,点到后就跟着分别去面试就好。三部分一天结束,预计结果要等一到两个月。(不太理解为什么等这么久)

    一、专业面试(其实更像挖简历的行为面?)

    我先被点到参加专业面试,据说在15mins左右,可是在我前面两位小姐姐都在20mins以上。进去后发现有三位面试官,两男一女,看起来很有资历了前面有一个位子面试者坐,隔得比较远。问好后首先就是万年不变的自我介绍,以及对本人来说,万年不变的“专业不对口”问题。接着对我的实习经历进行了深挖。包括怎么写报告的?报告有哪些亮点?等等。
    三位都有问,且侧重点不同。中间一位侧重需求设计,问我对需求设计有什么理解?我利用了产品经理的相关知识,先说产品的生命周期第一步就是需求设计,并列举了需求设计的三个过程,以及其中的具体方法。面试官指出银行的产品有所不同,需求之后直接输出需求文档及原型转给开发人员,而不像互联网一样先给用户定位和画像。紧接着问如果开发技术不同意我的需求设计怎么办(举了一个最近的例子,一个PM和程序员因为一个需求打起来了)?我答先从自身找问题,再诚心与技术人员沟通。这里强调了产品(需求)人员懂点技术的重要性(“嗯嗯,您说的很有道理”)。后来又问了为什么不继续在券商实习?如果给你offer,同时又有券商基金的offer,该怎么选择?我举了一个例子,如果我是踢球的,皇马巴萨两家俱乐部都想签我,我会考虑自身的特点以及他给的位置和战术安排。最后强调相比之下,总行的信息科技岗对我的吸引力还是很大的!估计他也是球迷吧,听了我这个回答会心一笑。
    右边的女面试官详细问了我公众号的运营经历以及写研究报告的过程。
    左边的面试官很关心我的计算机水平,我自然是要摆低姿态,毕竟小白一个,只自学了一点python而已。后来他问我对计算机本身的了解?有没有拆过计算机?我只好说不好意思了(只有一次因为风扇太吵,拆过一次清灰)。又问我平时关注互联网新闻吗?这个我给了肯定的回答。后面又问我区块链,我只懂一个大概,并说最大特点是去中心化记账。他的这一系列问题我没回答好,也看出了他的失望。还是平时积累不够!!这一块要加强!!

    二、综合面

    六人一组进到一个小房间。六对三面试。每人抽一个话题表达自己的看法。我抽到“如何看待选秀(例如创造101)对青少年的影响?利大于弊抑或弊大于利”。我从三个方面,理性、感性角度及节目本身的特点进行了阐述,结论利大于弊。六个人有三位抽到了这个话题,都支持利大于弊。另三位抽到的是“如何看待高铁吸烟的问题”。个人认为这个不太好说。
    随后面试官问了三位:介绍一下你写的一篇论文;另外三位(包括我):你认为你的优势是什么。一位面试官突然Q我(大概我是这场唯一的男生??),有软件开发经验吗,我表示遗憾,外加生无可恋。。。

    三、机考(编程)

    前一天才知道要机考,只好临时抱了个佛脚,把自学的内容胡乱看了一遍。据说编程题比较简单,例如字符串逆转,大小写,数列求和等等。结果今天说需求设计方向不需要机考!瞬间长舒一口气哈哈哈哈。

    最后赞一下耐心负责的现场面试官和工作人员,以及食堂!
    欢迎小伙伴交流!

    1.7 秋招面经(持续更新,攒RP 银联系统开发)

    作者:ㄣArviiinズ
    链接:https://www.nowcoder.com/discuss/90894
    来源:牛客网

    1.浦发银行总行信息科技部面试(2018.8.5 12.30场)

    综合面:

    三个面试官,6个人,每人给一份材料,一支笔,2分钟阅读材料,3分钟演讲,我的是怎么看待格力董明珠要不要做芯片 我没抽到的另一个是:你怎么看网络综艺和电视台综艺.

    结束后会有提问,有的问自我介绍,有的问自己的优点等,但是我很奇葩的被问了看了什么论文。

    技术面:

    三个面试官对着你一个人,开始就是自我介绍,对着你介绍的问,所以说的时候不要给自己挖坑,技术点细节不怎么问,另外不要把问题想复杂,我有的问题说的太细了,面试官就说可以了,下一个问题。

    机试:

    三道题,第一题:分段函数。第二题:A,B两个字符串,求在第一个字符串出现,第二个字符串中未出现的,重复只取第一次出现,输出字符串。第三题加密解密,就是给你由大写字母组成的字符串,求出原来的字符串,加密 。方式很简单就是字符串后移五位,比如原来是A加密后是F,其余数字等标点符号原样输出.

    总结:时间持续的蛮久的,都是在等的状态,我四点多结束的.

    2.浦发银行总行信息科技部面试(2018.8.9 9.30场)
    到了以后交材料,然后填一个很详细的表,4页.太可怕了.
    群面:2个面试官12个人无领导小组讨论,每人给一份材料,一支铅笔,一张白纸5分钟阅读材料,1分钟自我介绍并回答材料问题,关于金融风险的排序问题.接下来20分钟的自由讨论和3分钟的陈述总结.刷的人不多,面试官也不看我们.

    技术面: 2个面试官对你一个人,开始就是上交简历自我介绍。然后对着简历问问题.我问到了hashMap,反射实现的机制.高并发,还有一些关于自己项目和实习经历的.人还是很nice的,聊的还不错.

    总结:,效率和时间安排还可以,我快12.30结束的.

    1.8 上海浦发面经(秋招面经持续更新,攒人品)

    作者:我只是弱鸡
    链接:https://www.nowcoder.com/discuss/90871
    来源:牛客网

    8.4日,大数据方向,共两面,加上机

    综合面:6个人,每人给一份材料,2分钟阅读材料,3分钟演讲,我的是怎么看待,app,纸质阅读,等多样化阅读,并保持阅读高效性

    另外一个材料:中国生产圆珠笔里的主要材料都是进口的,但却是圆珠笔产量第一的国家,你怎么看?

    结束后会有提问,自我介绍,关于材料哪位同学讲的好之类。

    技术面:自我介绍,会问项目的内容,你对投递岗位的理解,你做的项目如果用到银行会有什么应用,技术点不怎么问。

    上机:可选项,可做可不做(开发方向上机必须,题都基础)。三道题,第一题,从求组中找出唯一出现一次得数。第二题,给年月日,判断是方面第几天。第三题,小球从100米下落,每次回弹一半距离,第几次落地后的总距离。

    1.9 浦发银行现场面(武汉地区)

    作者:珞珈山落草为寇
    链接:https://www.nowcoder.com/discuss/90567
    来源:牛客网

    七月三十一号浦发现场面试,记录下,回馈牛友.
    面试三项流程:结构化面试+即兴演讲+机试
    结构化面试分为两组:每组三个面试官,主要就是对着简历问.
    面试官会让你自我介绍,我介绍的很简短,简历上已有的内容就没介绍,结果面试官让我自己把自己的项目也介绍下(面试官太懒,想听你说)
    有个面试官看见我写的Java项目,就问了几个Java的水题,比如接口和类的区别,常用集合类等.
    然后就出去等候下一轮召唤.
    接下来就是机试,机试很水,三道题,每题代码量不超过十行(可以用Eclipse/Notepa++)
    字符串逆序输出,数列和,小写转大写
    好像用的是华科的OJ评测系统.
    最后一轮是即兴演讲面.6个人一组,抽题目,两分钟读题,三分钟陈述观点.
    总结:面试很耗时,效率很低.中午12.30开始,一直拖动下午五点多才结束.
    面试结果未知,群里说有等一个月或者几个月的.

    1.10 浦发银行(西安分行)信息科技岗面经

    作者:neu张康
    链接:https://www.nowcoder.com/discuss/89581
    来源:牛客网

    先说一下,我投的是(系统开发方向)
    一面:群面,6人一组,每人抽一题,看2分钟然后进行个人演讲。6个人都完事后面试官会问你,你觉得本次演讲谁最突出,推荐2人。
    二面:技术面,三位面试官,问得问题范围比较大,细节问得不多。首先是自我介绍,因为我写的项目中涉及到高并发,然后问从代码的角度如何优化(回答的好像不满意)。其次又问了java的开源框架都熟悉哪些,我说了spring,然后就问了IOC和AOP。然后又问熟悉tomcat吗,配置连接池的时候如何配置最大连接数。然后又问了问研究生期间做的什么,然后就没有然后了。java虚拟机,集合,线程什么的一点没问。
    三面:机考,三个编程题。
    第一题:把字符串中的字符a和A换成c输出。
    第二题:给你年月日,求出是这年的第几天
    第三题:给你两个数,例如23和456,23456=24 25 26 34 35 3*6,让你实现这个算法。

    展开全文
  • 多线程面试题(值得收藏)

    万次阅读 多人点赞 2019-08-16 09:41:18
    金九银十到了,即将进入找工作的高峰期,最新整理的最全多线程并发面试47题和答案总结,希望对想进BAT的同学有帮助,由于篇幅较长,建议收藏后细看~ 1、并发编程三要素? 1)原子性 原子性指的是一个或者多个操作,...

    史上最强多线程面试47题(含答案),建议收藏

    金九银十快到了,即将进入找工作的高峰期,最新整理的最全多线程并发面试47题和答案总结,希望对想进BAT的同学有帮助,由于篇幅较长,建议收藏后细看~

    1、并发编程三要素?

    1)原子性

    原子性指的是一个或者多个操作,要么全部执行并且在执行的过程中不被其他操作打断,要么就全部都不执行。

    2)可见性

    可见性指多个线程操作一个共享变量时,其中一个线程对变量进行修改后,其他线程可以立即看到修改的结果。

    3)有序性

    有序性,即程序的执行顺序按照代码的先后顺序来执行。

    2、实现可见性的方法有哪些?

    synchronized或者Lock:保证同一个时刻只有一个线程获取锁执行代码,锁释放之前把最新的值刷新到主内存,实现可见性。

    3、多线程的价值?

    1)发挥多核CPU的优势

    多线程,可以真正发挥出多核CPU的优势来,达到充分利用CPU的目的,采用多线程的方式去同时完成几件事情而不互相干扰。

    2)防止阻塞

    从程序运行效率的角度来看,单核CPU不但不会发挥出多线程的优势,反而会因为在单核CPU上运行多线程导致线程上下文的切换,而降低程序整体的效率。但是单核CPU我们还是要应用多线程,就是为了防止阻塞。试想,如果单核CPU使用单线程,那么只要这个线程阻塞了,比方说远程读取某个数据吧,对端迟迟未返回又没有设置超时时间,那么你的整个程序在数据返回回来之前就停止运行了。多线程可以防止这个问题,多条线程同时运行,哪怕一条线程的代码执行读取数据阻塞,也不会影响其它任务的执行。

    3)便于建模

    这是另外一个没有这么明显的优点了。假设有一个大的任务A,单线程编程,那么就要考虑很多,建立整个程序模型比较麻烦。但是如果把这个大的任务A分解成几个小任务,任务B、任务C、任务D,分别建立程序模型,并通过多线程分别运行这几个任务,那就简单很多了。

    4、创建线程的有哪些方式?

    1)继承Thread类创建线程类

    2)通过Runnable接口创建线程类

    3)通过Callable和Future创建线程

    4)通过线程池创建

    5、创建线程的三种方式的对比?

    1)采用实现Runnable、Callable接口的方式创建多线程。

    优势是:

    线程类只是实现了Runnable接口或Callable接口,还可以继承其他类。

    在这种方式下,多个线程可以共享同一个target对象,所以非常适合多个相同线程来处理同一份资源的情况,从而可以将CPU、代码和数据分开,形成清晰的模型,较好地体现了面向对象的思想。

    劣势是:

    编程稍微复杂,如果要访问当前线程,则必须使用Thread.currentThread()方法。

    2)使用继承Thread类的方式创建多线程

    优势是:

    编写简单,如果需要访问当前线程,则无需使用Thread.currentThread()方法,直接使用this即可获得当前线程。

    劣势是:

    线程类已经继承了Thread类,所以不能再继承其他父类。

    3)Runnable和Callable的区别

    Callable规定(重写)的方法是call(),Runnable规定(重写)的方法是run()。
    Callable的任务执行后可返回值,而Runnable的任务是不能返回值的。
    Call方法可以抛出异常,run方法不可以。
    运行Callable任务可以拿到一个Future对象,表示异步计算的结果。它提供了检查计算是否完成的方法,以等待计算的完成,并检索计算的结果。通过Future对象可以了解任务执行情况,可取消任务的执行,还可获取执行结果。

    6、线程的状态流转图

    线程的生命周期及五种基本状态:

    7、Java线程具有五中基本状态

    1)新建状态(New):当线程对象对创建后,即进入了新建状态,如:Thread t = new MyThread();

    2)就绪状态(Runnable):当调用线程对象的start()方法(t.start();),线程即进入就绪状态。处于就绪状态的线程,只是说明此线程已经做好了准备,随时等待CPU调度执行,并不是说执行了t.start()此线程立即就会执行;

    3)运行状态(Running):当CPU开始调度处于就绪状态的线程时,此时线程才得以真正执行,即进入到运行状态。注:就
    绪状态是进入到运行状态的唯一入口,也就是说,线程要想进入运行状态执行,首先必须处于就绪状态中;

    4)阻塞状态(Blocked):处于运行状态中的线程由于某种原因,暂时放弃对CPU的使用权,停止执行,此时进入阻塞状态,直到其进入到就绪状态,才 有机会再次被CPU调用以进入到运行状态。

    根据阻塞产生的原因不同,阻塞状态又可以分为三种:

    a.等待阻塞:运行状态中的线程执行wait()方法,使本线程进入到等待阻塞状态;

    b.同步阻塞 – 线程在获取synchronized同步锁失败(因为锁被其它线程所占用),它会进入同步阻塞状态;

    c.其他阻塞 – 通过调用线程的sleep()或join()或发出了I/O请求时,线程会进入到阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态。

    5)死亡状态(Dead):线程执行完了或者因异常退出了run()方法,该线程结束生命周期。

    8、什么是线程池?有哪几种创建方式?

    线程池就是提前创建若干个线程,如果有任务需要处理,线程池里的线程就会处理任务,处理完之后线程并不会被销毁,而是等待下一个任务。由于创建和销毁线程都是消耗系统资源的,所以当你想要频繁的创建和销毁线程的时候就可以考虑使用线程池来提升系统的性能。

    java 提供了一个 java.util.concurrent.Executor接口的实现用于创建线程池。

    9、四种线程池的创建:

    1)newCachedThreadPool创建一个可缓存线程池

    2)newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数。

    3)newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行。

    4)newSingleThreadExecutor 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务。

    10、线程池的优点?

    1)重用存在的线程,减少对象创建销毁的开销。

    2)可有效的控制最大并发线程数,提高系统资源的使用率,同时避免过多资源竞争,避免堵塞。

    3)提供定时执行、定期执行、单线程、并发数控制等功能。

    11、常用的并发工具类有哪些?

    CountDownLatch
    CyclicBarrier
    Semaphore
    Exchanger

    12、CyclicBarrier和CountDownLatch的区别

    1)CountDownLatch简单的说就是一个线程等待,直到他所等待的其他线程都执行完成并且调用countDown()方法发出通知后,当前线程才可以继续执行。

    2)cyclicBarrier是所有线程都进行等待,直到所有线程都准备好进入await()方法之后,所有线程同时开始执行!

    3)CountDownLatch的计数器只能使用一次。而CyclicBarrier的计数器可以使用reset() 方法重置。所以CyclicBarrier能处理更为复杂的业务场景,比如如果计算发生错误,可以重置计数器,并让线程们重新执行一次。

    4)CyclicBarrier还提供其他有用的方法,比如getNumberWaiting方法可以获得CyclicBarrier阻塞的线程数量。isBroken方法用来知道阻塞的线程是否被中断。如果被中断返回true,否则返回false。

    13、synchronized的作用?

    在Java中,synchronized关键字是用来控制线程同步的,就是在多线程的环境下,控制synchronized代码段不被多个线程同时执行。

    synchronized既可以加在一段代码上,也可以加在方法上。

    14、volatile关键字的作用

    对于可见性,Java提供了volatile关键字来保证可见性。

    当一个共享变量被volatile修饰时,它会保证修改的值会立即被更新到主存,当有其他线程需要读取时,它会去内存中读取新值。

    从实践角度而言,volatile的一个重要作用就是和CAS结合,保证了原子性,详细的可以参见java.util.concurrent.atomic包下的类,比如AtomicInteger。

    15、什么是CAS

    CAS是compare and swap的缩写,即我们所说的比较交换。

    cas是一种基于锁的操作,而且是乐观锁。在java中锁分为乐观锁和悲观锁。悲观锁是将资源锁住,等一个之前获得锁的线程释放锁之后,下一个线程才可以访问。而乐观锁采取了一种宽泛的态度,通过某种方式不加锁来处理资源,比如通过给记录加version来获取数据,性能较悲观锁有很大的提高。

    CAS 操作包含三个操作数 —— 内存位置(V)、预期原值(A)和新值(B)。如果内存地址里面的值和A的值是一样的,那么就将内存里面的值更新成B。CAS是通过无限循环来获取数据的,若果在第一轮循环中,a线程获取地址里面的值被b线程修改了,那么a线程需要自旋,到下次循环才有可能机会执行。

    java.util.concurrent.atomic 包下的类大多是使用CAS操作来实现的( AtomicInteger,AtomicBoolean,AtomicLong)。

    16、CAS的问题

    1)CAS容易造成ABA问题

    一个线程a将数值改成了b,接着又改成了a,此时CAS认为是没有变化,其实是已经变化过了,而这个问题的解决方案可以使用版本号标识,每操作一次version加1。在java5中,已经提供了AtomicStampedReference来解决问题。

    2) 不能保证代码块的原子性

    CAS机制所保证的知识一个变量的原子性操作,而不能保证整个代码块的原子性。比如需要保证3个变量共同进行原子性的更新,就不得不使用synchronized了。

    3)CAS造成CPU利用率增加

    之前说过了CAS里面是一个循环判断的过程,如果线程一直没有获取到状态,cpu资源会一直被占用。

    17、什么是Future?

    在并发编程中,我们经常用到非阻塞的模型,在之前的多线程的三种实现中,不管是继承thread类还是实现runnable接口,都无法保证获取到之前的执行结果。通过实现Callback接口,并用Future可以来接收多线程的执行结果。

    Future表示一个可能还没有完成的异步任务的结果,针对这个结果可以添加Callback以便在任务执行成功或失败后作出相应的操作。

    18、什么是AQS

    AQS是AbustactQueuedSynchronizer的简称,它是一个Java提高的底层同步工具类,用一个int类型的变量表示同步状态,并提供了一系列的CAS操作来管理这个同步状态。

    AQS是一个用来构建锁和同步器的框架,使用AQS能简单且高效地构造出应用广泛的大量的同步器,比如我们提到的ReentrantLock,Semaphore,其他的诸如ReentrantReadWriteLock,SynchronousQueue,FutureTask等等皆是基于AQS的。

    19、AQS支持两种同步方式:

    1)独占式

    2)共享式

    这样方便使用者实现不同类型的同步组件,独占式如ReentrantLock,共享式如Semaphore,CountDownLatch,组合式的如ReentrantReadWriteLock。总之,AQS为使用提供了底层支撑,如何组装实现,使用者可以自由发挥。

    20、ReadWriteLock是什么

    首先明确一下,不是说ReentrantLock不好,只是ReentrantLock某些时候有局限。如果使用ReentrantLock,可能本身是为了防止线程A在写数据、线程B在读数据造成的数据不一致,但这样,如果线程C在读数据、线程D也在读数据,读数据是不会改变数据的,没有必要加锁,但是还是加锁了,降低了程序的性能。

    因为这个,才诞生了读写锁ReadWriteLock。ReadWriteLock是一个读写锁接口,ReentrantReadWriteLock是ReadWriteLock接口的一个具体实现,实现了读写的分离,读锁是共享的,写锁是独占的,读和读之间不会互斥,读和写、写和读、写和写之间才会互斥,提升了读写的性能。

    21、FutureTask是什么

    这个其实前面有提到过,FutureTask表示一个异步运算的任务。FutureTask里面可以传入一个Callable的具体实现类,可以对这个异步运算的任务的结果进行等待获取、判断是否已经完成、取消任务等操作。当然,由于FutureTask也是Runnable接口的实现类,所以FutureTask也可以放入线程池中。

    22、synchronized和ReentrantLock的区别

    synchronized是和if、else、for、while一样的关键字,ReentrantLock是类,这是二者的本质区别。既然ReentrantLock是类,那么它就提供了比synchronized更多更灵活的特性,可以被继承、可以有方法、可以有各种各样的类变量,ReentrantLock比synchronized的扩展性体现在几点上:

    1)ReentrantLock可以对获取锁的等待时间进行设置,这样就避免了死锁

    2)ReentrantLock可以获取各种锁的信息

    3)ReentrantLock可以灵活地实现多路通知

    另外,二者的锁机制其实也是不一样的。ReentrantLock底层调用的是Unsafe的park方法加锁,synchronized操作的应该是对象头中mark word,这点我不能确定。

    23、什么是乐观锁和悲观锁

    1)乐观锁:就像它的名字一样,对于并发间操作产生的线程安全问题持乐观状态,乐观锁认为竞争不总是会发生,因此它不需要持有锁,将比较-替换这两个动作作为一个原子操作尝试去修改内存中的变量,如果失败则表示发生冲突,那么就应该有相应的重试逻辑。

    2)悲观锁:还是像它的名字一样,对于并发间操作产生的线程安全问题持悲观状态,悲观锁认为竞争总是会发生,因此每次对某资源进行操作时,都会持有一个独占的锁,就像synchronized,不管三七二十一,直接上了锁就操作资源了。

    24、线程B怎么知道线程A修改了变量

    volatile修饰变量
    synchronized修饰修改变量的方法
    wait/notify
    while轮询

    25、synchronized、volatile、CAS比较

    synchronized是悲观锁,属于抢占式,会引起其他线程阻塞。
    volatile提供多线程共享变量可见性和禁止指令重排序优化。
    CAS是基于冲突检测的乐观锁(非阻塞)

    26、sleep方法和wait方法有什么区别?

    这个问题常问,sleep方法和wait方法都可以用来放弃CPU一定的时间,不同点在于如果线程持有某个对象的监视器,sleep方法不会放弃这个对象的监视器,wait方法会放弃这个对象的监视器

    27、ThreadLocal是什么?有什么用?

    ThreadLocal是一个本地线程副本变量工具类。主要用于将私有线程和该线程存放的副本对象做一个映射,各个线程之间的变量互不干扰,在高并发场景下,可以实现无状态的调用,特别适用于各个线程依赖不通的变量值完成操作的场景。

    简单说ThreadLocal就是一种以空间换时间的做法,在每个Thread里面维护了一个以开地址法实现的ThreadLocal.ThreadLocalMap,把数据进行隔离,数据不共享,自然就没有线程安全方面的问题了。

    28、为什么wait()方法和notify()/notifyAll()方法要在同步块中被调用

    这是JDK强制的,wait()方法和notify()/notifyAll()方法在调用前都必须先获得对象的锁

    29、多线程同步有哪几种方法?

    Synchronized关键字,Lock锁实现,分布式锁等。

    30、线程的调度策略

    线程调度器选择优先级最高的线程运行,但是,如果发生以下情况,就会终止线程的运行:

    1)线程体中调用了yield方法让出了对cpu的占用权利

    2)线程体中调用了sleep方法使线程进入睡眠状态

    3)线程由于IO操作受到阻塞

    4)另外一个更高优先级线程出现

    5)在支持时间片的系统中,该线程的时间片用完

    31、ConcurrentHashMap的并发度是什么

    ConcurrentHashMap的并发度就是segment的大小,默认为16,这意味着最多同时可以有16条线程操作ConcurrentHashMap,这也是ConcurrentHashMap对Hashtable的最大优势,任何情况下,Hashtable能同时有两条线程获取Hashtable中的数据吗?

    32、Linux环境下如何查找哪个线程使用CPU最长

    1)获取项目的pid,jps或者ps -ef | grep java,这个前面有讲过

    2)top -H -p pid,顺序不能改变

    33、Java死锁以及如何避免?

    Java中的死锁是一种编程情况,其中两个或多个线程被永久阻塞,Java死锁情况出现至少两个线程和两个或更多资源。

    Java发生死锁的根本原因是:在申请锁时发生了交叉闭环申请。

    34、死锁的原因

    1)是多个线程涉及到多个锁,这些锁存在着交叉,所以可能会导致了一个锁依赖的闭环。

    例如:线程在获得了锁A并且没有释放的情况下去申请锁B,这时,另一个线程已经获得了锁B,在释放锁B之前又要先获得锁A,因此闭环发生,陷入死锁循环。

    2)默认的锁申请操作是阻塞的。

    所以要避免死锁,就要在一遇到多个对象锁交叉的情况,就要仔细审查这几个对象的类中的所有方法,是否存在着导致锁依赖的环路的可能性。总之是尽量避免在一个同步方法中调用其它对象的延时方法和同步方法。

    35、怎么唤醒一个阻塞的线程

    如果线程是因为调用了wait()、sleep()或者join()方法而导致的阻塞,可以中断线程,并且通过抛出InterruptedException来唤醒它;如果线程遇到了IO阻塞,无能为力,因为IO是操作系统实现的,Java代码并没有办法直接接触到操作系统。

    36、不可变对象对多线程有什么帮助

    前面有提到过的一个问题,不可变对象保证了对象的内存可见性,对不可变对象的读取不需要进行额外的同步手段,提升了代码执行效率。

    37、什么是多线程的上下文切换

    多线程的上下文切换是指CPU控制权由一个已经正在运行的线程切换到另外一个就绪并等待获取CPU执行权的线程的过程。

    38、如果你提交任务时,线程池队列已满,这时会发生什么

    这里区分一下:

    1)如果使用的是无界队列LinkedBlockingQueue,也就是无界队列的话,没关系,继续添加任务到阻塞队列中等待执行,因为LinkedBlockingQueue可以近乎认为是一个无穷大的队列,可以无限存放任务

    2)如果使用的是有界队列比如ArrayBlockingQueue,任务首先会被添加到ArrayBlockingQueue中,ArrayBlockingQueue满了,会根据maximumPoolSize的值增加线程数量,如果增加了线程数量还是处理不过来,ArrayBlockingQueue继续满,那么则会使用拒绝策略RejectedExecutionHandler处理满了的任务,默认是AbortPolicy

    39、Java中用到的线程调度算法是什么

    抢占式。一个线程用完CPU之后,操作系统会根据线程优先级、线程饥饿情况等数据算出一个总的优先级并分配下一个时间片给某个线程执行。

    40、什么是线程调度器(Thread Scheduler)和时间分片(Time Slicing)?

    线程调度器是一个操作系统服务,它负责为Runnable状态的线程分配CPU时间。一旦我们创建一个线程并启动它,它的执行便依赖于线程调度器的实现。时间分片是指将可用的CPU时间分配给可用的Runnable线程的过程。分配CPU时间可以基于线程优先级或者线程等待的时间。线程调度并不受到Java虚拟机控制,所以由应用程序来控制它是更好的选择(也就是说不要让你的程序依赖于线程的优先级)。

    41、什么是自旋

    很多synchronized里面的代码只是一些很简单的代码,执行时间非常快,此时等待的线程都加锁可能是一种不太值得的操作,因为线程阻塞涉及到用户态和内核态切换的问题。既然synchronized里面的代码执行得非常快,不妨让等待锁的线程不要被阻塞,而是在synchronized的边界做忙循环,这就是自旋。如果做了多次忙循环发现还没有获得锁,再阻塞,这样可能是一种更好的策略。

    42、Java
    Concurrency API中的Lock接口(Lock
    interface)是什么?对比同步它有什么优势?

    Lock接口比同步方法和同步块提供了更具扩展性的锁操作。他们允许更灵活的结构,可以具有完全不同的性质,并且可以支持多个相关类的条件对象。

    它的优势有:

    可以使锁更公平
    可以使线程在等待锁的时候响应中断
    可以让线程尝试获取锁,并在无法获取锁的时候立即返回或者等待一段时间
    可以在不同的范围,以不同的顺序获取和释放锁

    43、单例模式的线程安全性

    老生常谈的问题了,首先要说的是单例模式的线程安全意味着:某个类的实例在多线程环境下只会被创建一次出来。单例模式有很多种的写法,我总结一下:

    1)饿汉式单例模式的写法:线程安全

    2)懒汉式单例模式的写法:非线程安全

    3)双检锁单例模式的写法:线程安全

    44、Semaphore有什么作用

    Semaphore就是一个信号量,它的作用是限制某段代码块的并发数。Semaphore有一个构造函数,可以传入一个int型整数n,表示某段代码最多只有n个线程可以访问,如果超出了n,那么请等待,等到某个线程执行完毕这段代码块,下一个线程再进入。由此可以看出如果Semaphore构造函数中传入的int型整数n=1,相当于变成了一个synchronized了。

    45、Executors类是什么?

    Executors为Executor,ExecutorService,ScheduledExecutorService,ThreadFactory和Callable类提供了一些工具方法。

    Executors可以用于方便的创建线程池

    46、线程类的构造方法、静态块是被哪个线程调用的

    这是一个非常刁钻和狡猾的问题。请记住:线程类的构造方法、静态块是被new这个线程类所在的线程所调用的,而run方法里面的代码才是被线程自身所调用的。

    如果说上面的说法让你感到困惑,那么我举个例子,假设Thread2中new了Thread1,main函数中new了Thread2,那么:

    1)Thread2的构造方法、静态块是main线程调用的,Thread2的run()方法是Thread2自己调用的

    2)Thread1的构造方法、静态块是Thread2调用的,Thread1的run()方法是Thread1自己调用的

    47、同步方法和同步块,哪个是更好的选择?

    同步块,这意味着同步块之外的代码是异步执行的,这比同步整个方法更提升代码的效率。请知道一条原则:同步的范围越小越好。

    48、Java线程数过多会造成什么异常?

    1)线程的生命周期开销非常高

    2)消耗过多的CPU资源

    如果可运行的线程数量多于可用处理器的数量,那么有线程将会被闲置。大量空闲的线程会占用许多内存,给垃圾回收器带来压力,而且大量的线程在竞争CPU资源时还将产生其他性能的开销。

    3)降低稳定性

    JVM在可创建线程的数量上存在一个限制,这个限制值将随着平台的不同而不同,并且承受着多个因素制约,包括JVM的启动参数、Thread构造函数中请求栈的大小,以及底层操作系统对线程的限制等。如果破坏了这些限制,那么可能抛出OutOfMemoryError异常。

    展开全文
  • 2021【软件测试】面试题合集大放送

    万次阅读 多人点赞 2019-09-10 18:04:37
    到了金九银十跳槽求职旺季。准备一场面试不仅需要在简历上多下功夫,还需要为面试问答做好充足的准备,简历书写请参考:https://blog.csdn.net/leboxy/article/details/100658701。以下是“大佬”本人从乐搏学院...
  • 《人工智能杂记》人工智能时间简史

    万次阅读 多人点赞 2018-03-13 08:54:55
    人说话时,是与物理事件学相联系的,比如一个人说电脑,人知道这个电脑意味着什么,或者它是能够干些什么,而在自然语言里,它仅仅将"电脑"作为一个孤立的词,不会去产生类似的联想,自然语言的联想只是通过在文本上...
  • 基于Java的毕业设计管理系统

    万次阅读 多人点赞 2016-08-27 10:09:11
    、做界面原型的时候,没有为界面起名字,导致后来看着不知道只干什么,若是团队合作的会使团队其他人在看代码时感觉很凌乱。 2 、在建数据库的时候,未设置外键,因为对数据库不熟。 4 、用 JSP 写页面布局...
  • 如何快速成为一个运维工程师

    万次阅读 多人点赞 2018-05-24 16:08:49
    首先先看图:下面是运维工程师至少要能做以下的工作:1,网络工程师的工作你至少要能配置CISCO 6509以下的设备,熟悉各种网络协议,否则网络出问题的时候你会傻掉。2,系统工程师的工作你至少要理解各种系统服务,在...
  • 系统程序员成长计划-写得又快又好的秘诀(三)

    千次阅读 热门讨论 2009-10-09 10:16:00
    这种代码阅读法会花你一些时间,但是可以省下更多调试时间,而且能够提高代码质量,可以说是名符其实的“又快又好的” 秘诀之一。至于读几遍合适,要根据情况而定,个人觉得读两到三遍是最佳的投资。
  • 同样都可以对数据构建索引并通过索引查询数据,为什么Lucene或基于Lucene的Elasticsearch会比关系型数据库如MySQL搜索性能更优?... 本文将从以下各模块进行阐述:什么是索引MySQL索引是如何实现...
  • 如何优雅地向公司加薪

    千次阅读 热门讨论 2020-06-09 08:32:07
    以上是读者奔三十私信我的问题,很有代表性,我计划着好好写一篇文章来统一回复下,结果一拖再拖,拖了一个月时间,真的非常非常抱歉。 我之所以拖,有两个原因。第一个原因就是这个问题确实不太回答,因为我...
  • 知识图谱构建技术一览

    万次阅读 多人点赞 2019-09-03 23:21:11
    知识图谱构建技术一览一、什么是知识图谱二、知识图谱技术架构(一)数据获取(Data Acquisition)(二)信息抽取(Information Extraction)(1)实体抽取(Entity Extraction)/命名实体识别(Name Entity ...
  • 家里宽带升级到200M了,请用过的童鞋推荐一款千兆路由器...如果继续使用老的百兆路由器的话,你家的网速就会造成大量的浪费的,这时候你就需要一款千兆路由器。而很多卖路由器的会用宣传它是千兆路由器,实际上它不...
  • 什么是真正的程序员

    万次阅读 多人点赞 2020-10-16 10:18:10
    这篇文章的原文来自:A Little Printf Story作者仿照《小王子》中的情节,通过小printf遇见的不同类型的程序员,最后悟出什么才是真正的程序员!第一次翻译有很多不妥,欢迎留言指正。 文章略长,但是耐心读完,你...
  • 首先给大家介绍什么叫大数据,大数据最早是在2006年谷歌出来的,百度给他的定义为巨量数据集合,辅相成在今天大数据技术随着互联网的发展,更加迅速的成长,小到个人,企业,达到国家安全,大数据的作用可见一斑,...
  • 什么redis 是单线程的?

    万次阅读 多人点赞 2018-02-26 21:38:17
    在说这个事前希望大家都能对 CPU 、 内存 、 硬盘的速度都有了解了,这样可能理解得更深刻一点,不了解的朋友点:CPU到底比内存跟硬盘多少redis 核心就是 如果我的数据全都在内存里,我单线程的去操作 就是效率...
  • 前言:以前我说过不准备写这个排,一是我自己的网站没有操作过所谓的排 ,二是我并不能像...我只是站在一个小白角度,让更多小白了解下所谓百度排是什么,以及同行网站是否使用了所谓排技术,我们自己...
  • 程序员:你30岁前的职业规划是什么?未来的职业规划什么
  • 如何简单形象有趣地讲解神经网络是什么? 有网友在 Quora 上提问:对于那些非计算机科学行业的人,你会如何向他们解释机器学习和数据挖掘?  斯坦福大学的印度学生、机器学习爱好者 PararthShah 在2012年...
  • 遍地是钱,为什么捡不到?

    万次阅读 多人点赞 2021-04-06 00:13:59
    ,你没有气馁,你觉得中国电商还有机会,这时候头牌是易趣网,而且被美国头牌ebay收购了,中美头牌强强合并,这下总没跑了,赶紧去投奔,然后,被横空出世的淘宝直接击溃,市场份额从垄断到清零。 继续假设。 你...
  • 16年,平凡而收获的一年

    千次阅读 热门讨论 2016-12-31 22:01:48
    16年,平凡而收获的一年岁月如水,时间飞逝,转眼间,已经到了年尾,即将引来新的一年,我要赶紧抓住16年的尾巴,写篇文章记录一下我16年的点点滴滴。篇章大概如下,学习&工作室篇,实习篇,盛夏六月, 博客篇,...
  • 大家,我是二哥呀! 在某乎上看到一个话题,计算机专业,暑假需要提前自学吗,没想到,竟然上热榜了,说明很多高考完的同学觉悟太高了!害怕自己这个假期浪费了。 说句真心话,真不建议提前自学! 我担心有些同学...
  •   4月8日华为终于在国内线上...那么华为这波整活到底是为了什么呢?和这应用服务有关系吗?   对于华为应用大家可能会比较了解,其对标的是微信小程序,本质上是一个免下载的APP,那么对已一些用户流量不...
  • 本文是一篇介绍性入门的文章,对于很多已经了解git的朋友可以忽略此... 这个也不能喷,在学校的时候老师一直在培训大家如何写代码(可能都没有),从来都没有教大家如何管理自己的代码,导致自己的项目乱七八糟,让自己
  • 准备离职了,公司决定加薪留住我,是去是留?

    万次阅读 多人点赞 2020-05-24 10:28:45
    那你之后的工作心态多少会有点变化的,且不说你卖力不卖力吧,你领导也会杯弓蛇影的,你一些正常的举动,他都会觉得你什么想法了。 其次你想,你了离职,加薪留了下来,万一被你身边的仔知道,那......他们...
  • 至于经济学、政治学,都是讲了一堆有时都不一定能自圆其说的道理,且不理解上往往难度较高,即使真的理解了,也很少存在什么让人能一定要坚持的道理。 虽然口头上和心里觉得很多理论是不错, 但是为了这些抽象的...
  • 什么Elasticsearch比MySql的检索

    万次阅读 2018-11-19 17:22:08
    什么Elasticsearch比MySql的检索? Elasticsearch 是通过 Lucene 的倒排索引技术实现比关系型数据库更的过滤。特别是它对多条件的过滤支持非常,比如年龄在 18 和 30 之间,性别为女性这样的组合查询。倒排...
  • Angular 初学者快速上手教程

    万次阅读 多人点赞 2018-04-12 10:41:37
    课程介绍 本课程是一个系列基础教程,目标是带领读者...除了组件、路由、模块这 3 个核心小节具有很强的关联性之外,其它内容都是完全独立的,您可以在用到的时候再翻阅。 认真读完这个系列文章之后,您会深入理解...
  • 什么我说Rust是靠谱的编程语言

    万次阅读 多人点赞 2015-05-16 02:59:21
    ”,用于形容其工程量大、进度、成效显著。看看Rust的 Release Notes ,常见这类字眼: Version 1.0.0 (May 2015): ~1500 changes, numerous bugfixes Version 1.0.0-alpha.2 (February ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 167,007
精华内容 66,802
关键字:

又快又好是什么时候提的