测试开发工程师成长日记019 - 测试开发工程师面试知识点整理

本文详细介绍了Python和Java在测试开发中的关键概念,包括数据类型、内存管理和多线程。在Python中,强调了动态类型、闭包、装饰器、列表、元组和字典的区别,以及内存管理机制。而在Java中,讨论了基本数据类型、字符串处理、内存管理、多线程以及反射机制。此外,还涵盖了Linux常用命令和软件测试的目标与原则。
摘要由CSDN通过智能技术生成

测试开发工程师

一、python

Python3 中有六个标准的数据类型:

Number(数字)(包括整型、浮点型、复数、布尔型等)

String(字符串)

Tuple(元组)

List(列表)

Set(集合)

Dictionary(字典)

Python3 的六个标准数据类型中:

不可变数据(3 个):Number(数字)、String(字符串)、Tuple(元组)
可变数据(3 个):List(列表)、Dictionary(字典)、Set(集合)

1、深拷贝

深拷贝是将对象本身复制给另一个对象。这意味着如果对对象的副本进行更改时不会影响原对象。

​ 拷贝父对象,不会拷贝对象内部的子对象

浅拷贝是将对象的引用复制给另一个对象。因此,如果我们在副本中进行更改,则会影响原对象。

浅拷贝是copy模块中的方法,完全拷贝了子对象和父对象

2、is和==的区别

python是一种面向对象的语言,is和==是常用来进行对象比较, ==是用来比较两个对象的值是否相等;而is是比较两个对象是不是同一个,也就是指向同一块内存地址

类比java中==和equals的比较

==常用于相同的基本数据类型之间的比较,也可用于相同类型的对象之间的比较

1.如果比较的是基本数据类型,则比较的是二者的值;

2.如果比较的是对象,则比较的是对象的引用,即判断两个对象是否指向了同一块内存区域。

equals主要用于两个对象之间,检测一个对象是否等于另一个对象

1.类没有覆盖equals()方法,则通过equals()比较该类的两个对象时,等价于通过“==”比较这两个对象。(即判断两个对象是否指向了同一块内存区域)

2.类覆盖了equals()方法,比较两个对象的内容是否相等,若内容相等则返回true(认为对象相等)

3、闭包与装饰器的概念

闭包

定义:能够读取其他函数内部变量的函数

作用:保存外部函数的变量 ,不会随着外部函数调用完而销毁

形成条件:

  • 函数嵌套
  • 内部函数必须使用了外部函数的变量或者参数
  • 外部函数返回内部函数,这个使用了外部函数变量的内部函数称为闭包
img

这里的结果为11 其中外部函数num1 = 10 调用外部函数的变量num1 并输入参数num2 = 1

装饰器

定义: 实质上也是一个闭包函数,也就是说,也是一个函数嵌套 。

作用: 在不改变原函数的情况下,对已有函数进行额外的功能扩展。

形成条件:

  • 不修改已有函数的源代码
  • 不修改已有函数的调用方式
  • 给已有函数增加额外的功能

Python闭包和装饰器详解(以及区别)_墨鱼A的博客-CSDN博客_python闭包和装饰器的区别

4、Python是静态还是动态类型?是强类型还是弱类型?

  • 静态类型语言:变量定义时有类型声明的语言。

    (1)变量的类型在编译的时候确定

    (2)变量的类型在运行时不能修改

    (3)这样编译器就可以确定运行时需要的内存总量。
    例如:C、Scala、Java、F#语言是静态类型语言。

  • 动态类型语言:变量定义时无类型声明的语言。

    (1)变量的类型在运行的时候确定

    (2)变量的类型在运行可以修改

    例如:python、Javascript、Ruby语言是动态类型语言。

  • 强类型定义语言

    强制数据类型定义的语言。也就是说,一旦一个变量被指定了某个数据类型,如果不经过强制转换,那么它就永远是这个数据类型了。举个例子:如果你定义了一个整型变量a,那么程序根本不可能将a当作字符串类型处理。强类型定义语言是类型安全的语言。

    Java,Python在编译时期确定的变量类型且在运行时期不能改变。

  • 弱类型定义语言

    数据类型可以被忽略的语言。它与强类型定义语言相反, 一个变量可以赋不同数据类型的值。强类型定义语言在速度上可能略逊色于弱类型定义语言,但是强类型定义语言带来的严谨性能够有效的避免许多错误。

    Javascript:数字可以和字符串相加,会自动发生类型转换

5、可变对象与不可变对象有哪些?

可变对象:可以原处修改该数据对象;

不可变对象:必须创建新对象来保存修改后的数据。

python中可变对象包括:字典、集合、列表

​ 不可变对象包括:number(整型、浮点型、复数、布尔型)、String、元组

java中可变对象包括:除不可变对象之外

​ 不可变对象包括:八大基本数据类型(byte、short、int、long、float、double、char、boolean)和包装类及String类

6、面向对象的三大特点?什么是鸭子模型?

1、封装、继承、多态(同Java)

  • 封装:把属性和方法放到一个类里,再通过对象访问属性和方法;
  • 继承:父对象(父类)具有的属性或方法,子对象(子类)也可以有这些属性和方法;
  • 多态:同一种方法,不同的对象调用该方法,实现功能不一样,即对象可以表现出多种形态。

2、鸭子类型测试:指的是若看到一只鸟走起来像鸭子,游起来像鸭子,叫起来也像鸭子,那么这只鸟就可以被叫作鸭子。

由于支持鸭子类型测试,所有Python解释器不检测发生多态的对象是否继承同一个父类,只要它们有相同的行为(方法),它们之间就是多态的。

7、Python的内存管理机制?

python的内存管理机制就是引用计数器机制和垃圾回收机制的混合机制

①引用计数

引用计数增加

1.对象被创建:x=4

2.另外的别人被创建:y=x

3.被作为参数传递给函数:foo(x)

4.作为容器对象的一个元素:a=[1,x,‘33’]

引用计数减少

1.一个本地引用离开了它的作用域。比如上面的foo(x)函数结束时,x指向的对象引用减1。

2.对象的别名被显式的销毁:del x ;或者del y

3.对象的一个别名被赋值给其他对象:x=789

4.对象从一个窗口对象中移除:myList.remove(x)

5.窗口对象本身被销毁:del myList,或者窗口对象本身离开了作用域。

②垃圾回收

1、当内存中有不再使用的部分时,垃圾收集器就会把他们清理掉。它会去检查那些引用计数为0的对象,然后清除其在内存的空间。当然除了引用计数为0的会被清除,还有一种情况也会被垃圾收集器清掉:当两个对象相互引用时,他们本身其他的引用已经为0了

2、垃圾回收机制还有一个循环垃圾回收器, 确保释放循环引用对象(a引用b, b引用a, 导致其引用计数永远不为0)。

③内存池机制

Python中有分为大内存和小内存:(256K为界限分大小内存)

  • 大内存使用malloc进行分配
  • 小内存使用内存池进行分配

Python的内存池(金字塔):

第3层:最上层,用户对Python对象的直接操作

第1层和第2层:内存池,有Python的接口函数PyMem_Malloc实现-----若请求分配的内存在1~256字节之间就使用内存池管理系统进行分配,调用malloc函数分配内存,但是每次只会分配一块大小为256K的大块内存,不会调用free函数释放内存,将该内存块留在内存池中以便下次使用。

第0层:大内存-----若请求分配的内存大于256K,malloc函数分配内存,free函数释放内存。

第-1,-2层:操作系统进行操作

8、当内存溢出、泄漏应该如何处理?

1**、内存溢出**

原因:集合类中有很多对象的引用,使用完后未清空;代码中存在死循环或者循环产生了过多重复的对象实体;使用第三方软件中的bug:启动参数内存设定的过小

解决方案:

第一步,修改JVM启动参数,直接增加内存(-Xms,-Xmx参数一定不要忘记加);

第二步,检查错误日志,查看“OutOfMemory”错误前是否有其它异常或错误;

第三步,对代码进行走查和分析,找出可能发生内存溢出的位置;

重点排查以下几点:

  • 检查对数据库查询中,是否有一次获得全部数据的查询。一般来说,如果一次取十万条记录到内存,就可能引起内存溢出。这个问题比较隐蔽,在上线前,数据库中数据较少,不容易出问题,上线后,数据库中数据多了,一次查询就有可能引起内存溢出。因此对于数据库查询尽量采用分页的方式查询

  • 检查代码中是否有死循环或递归调用

  • 检查是否有大循环重复产生新对象实体

  • 检查List、MAP等集合对象是否有使用完后,未清除的问题。List、MAP等集合对象会始终存有对对象的引用,使得这些对象不能被GC回收。

第四步,使用内存查看工具动态查看内存使用情况。//Java中自带jmap可查看运行的堆内存情况

2、内存泄漏

思路:无论是哪种方式的内存泄露,最终表现的形式都是某些 python 对象在不停的增长;因此,首先是要找到这些异常的对象。

用到的工具: gc 模块和 objgraph 模块

  • gc模块 是Python的垃圾收集器模块,gc使用标记清除算法回收垃圾
  • objgraph 是一个用于诊断内存问题的工具

3、内存泄漏和内存溢出区别

内存溢出指向JVM申请内存空间时没有足够的可用内存了,就会抛出OOM即内存溢出

内存泄漏是指,向JVM申请了一块内存空间,使用完后没有释放,由于没有释放,这块内存区域其他类加载的时候无法申请,同时当前类又没有这块内存空间的内存地址了也无法使用,相当于丢了一块内存,这就是内存泄漏。值得注意的是内存泄漏最终会导致内存溢出,很好理解,内存丢了很多最后当然内存不够用了。

9、了解lambda函数吗?

  • lambda函数是一种匿名函数,即没有名字的函数
  • 使用lambda保留字定义,函数名是返回结果
  • lambda函数的函数体只是一个表达式
  • lambda函数用于定义简单的、能够在一行内表示的函数
  • lambda表达式” : “后面,只能有一个表达式,def则可以有多个
  • lambda一般用来定义简单的函数,而def可以定义复杂的函数
g=lambda x:x+1
print(g(1))
#结果为2

lambda作为一个表达式,定义了一个匿名函数。等价于 :

def g(x):
    return x+1

优点:代码更为简洁、紧凑;

缺点:代码看起来不太清晰,没有使用函数定义方式那么直观易理解。

10、python中列表、元组、字典的区别

相同:都是序列,序列即由索引和元素组成的。

区别

  • 列表(list):格式为 [‘…’ , ‘…’ , … ‘…’ ],用逗号分隔,用方括号括起来

    • 创建:list =[1, 2, ‘cook’]

    • 更新使用append(),删除使用del list[2]

  • 元组(tuple):元组的元素不能修改,使用小括号()

    • tip:元组中只有一个元素时,需要在元素后面加逗号,不然括号会被当成运算符使用

    • 创建:tup=(1, 2, ‘cook’)

    • 删除:del tuple( 要删除只能删除整个元组,不能删除元组的某个元素

    • 元组的元素不能修改,但是可以对元组连接组合:tup=tup1+tup2

  • 字典(dictionary): 个键值 key : value 对用冒号 : 分割 , 每个对之间用逗号(,)分割 ,整个字典包括在花括号 {} 中 ,

    • tip:作为 Python 的关键字和内置函数,变量名不建议命名为 dict

    • 创建: tinydict = {‘name’: ‘runoob’, ‘likes’: 123, ‘url’: ‘www.runoob.com’}

      • ​ tinydict = dict() #使用内置函数dict()创建字典
    • 修改:

      tinydict = {'Name': 'Runoob', 'Age': 7, 'Class': 'First'}
       
      tinydict['Age'] = 8               # 更新 Age
      tinydict['School'] = "菜鸟教程"  # 添加信息
      
    • 删除:

      tinydict = {'Name': 'Runoob', 'Age': 7, 'Class': 'First'}
      del tinydict['Name'] # 删除键 'Name'
      tinydict.clear()     # 清空字典
      del tinydict         # 删除字典,会引发异常,因为用执行del操作后字典不再存在   
       
      

总结

1.列表、元组和字典都是序列

2.列表、字典可以修改和删除序列中的某个元素,而元组就是一个整体,不能修改和删除,一定要修改或删除的话,只能修改和删除整个元组;

3.既然元组不能删除和修改,有什么作用呢?

​ 1.元组比列表遍历速度快,因为元组是一个整体,运算效率高;

​ 2.正是因为不能修改,元组可以保护不需要修改的数据,可以使代码结构更安全。

11、python如何把字典合并?

d1 = {'name': 'revotu', 'age': 99}
d2 = {'age': 24, 'sex': 'male'}
 
输出:
{'name': 'revotu', 'age': 24, 'sex': 'male'}

# 方法1,使用两次update方法向字典中添加元素
d = {}
d.update(d1)             
d.update(d2)
print(d)

# 方法2,先复制,后更新
d = d1.copy()           
d.update(d2)
print(d)

# 方法3,字典构造器 
d = dict(d1)              
d.update(d2)
print(d)
 
# 方法4,关键字参数hack
# 只有一行代码,看上去很酷,但是有一个问题,这种hack技巧只有在字典的键是【字符串】时才有效。
d = dict(d1, **d2)            
print(d)                     

# 方法5,字典推导式,字典推导式方法满足要求,只是嵌套的字典推导式,不那么清晰,不易于理解。
d = {k: v for d in [d1, d2] for k, v in d.items()}   
print(d)

# 方法6,元素拼接
d = dict(list(d1.items()) + list(d2.items()))        
print(d)

# 方法7,chain items        from itertools import chain
d = dict(chain(d1.items(), d2.items()))                
print(d)
 
# 方法8,itemscollections.ChainMap可将多个字典或映射,在逻辑上合并为一个单独的映射结构 
# 这种方法也很pythonic,而且也是通用方法     from collections import ChainMap
d = dict(ChainMap(d1, d2))                     
print(d)                                        

# 方法9,字典拆分
# 在Python3.5+中,可以使用一种全新的字典合并方式,这行代码很pythonic
d = {**d1, **d2}            
print(d)                     

12、获取当前目录下所有文件名(递归)

os 模块下有两个函数:

  • os.walk()

  • os.listdir()

    import os
     
    def file_name(file_dir):
        for root, dirs, files in os.walk(file_dir):
            print(root) #当前目录路径(包含所有子目录)
            print(dirs) #当前路径下所有子目录(同一路径下的存一个列表中)
            print(files) #当前路径下所有非目录子文件(同一路径下的存一个列表中)
    
    file_name("E:\\qzcsbj")
    
    

13、常用的正则表达式

正则:用来匹配字符串的一门表达式语言

1.支持普通字符

2.元字符:就一个符号来匹配一堆内容

    \d  能够匹配一个数字(0-9)

    \w  能够匹配数字,字母,下划线(0-9,a-z,A-Z,_)

    \W 除了数字,字母,下划线以外的内容

    \D 除了数字以外的内容

    [abc] 匹配a,b,c

    [^abc] 除了a, b,c

    .  除了换行符以外的其他所有内容都可以被匹配

3.量词:控制,前面元字符出现的频次

​ +:前面的元字符出现1次或多次,贪婪匹配的,尽可能多的拿到数据

​ *:前面的元字符出现0次或多次,贪婪匹配的.尽可能多的拿到数据

​ ?:前面的元字符出现0次或1次

14、python2 和python3的区别

1、 整数:python2中区分整型(int)和长整型(long),python3不区分**

2、 除法:python2中的整数相除属于整除,要想真除就得变成浮点数, python3中的整数相除就是真除

3、默认编码: python2–>ascii,3python–>utf-8

4、导入生成

  • 在导入模块运行时 python2 只会在模块同级目录下生成**.pyc文件**;
  • python 3生成__pycache__目录。

5、 print的区别

  • python2中print是一个语句,不论想输出什么,直接放到print关键字后面即可。
  • python3里,print()是一个函数,像其他函数一样,print()需要你将要输出的东西作为参数传给它。

6、 input的区别

  • python2有两个全局函数,用在命令行请求用户输入。①第一个叫input(),它等待用户输入一个python表达式(然后返回结果)。②第二个叫做raw_input(),用户输入什么他就返回什么。
  • python3 通过input替代了他们。

7、 xrange()

  • python2中有两种方法获得一定范围内的数字:①range(),返回一个列表 ②还有xrange(),返回一个可迭代对象 (惰性求值,使用的时候再生成) ;
  • python3里,range()返回可迭代对象,xrange()不再存在。

15、Python的常用包(库)有哪些?分别有什么作用?

1、Numpy(数值运算库)
2、Scipy(科学计算库)
3、Matplotlib(基础可视化库)
4、Pandas(数据处理库)
5、Seaborn(高级可视化库)
6、Scikit-learn(流行的机器学习库)
各自作用
1、Numpy是最为流行的机器学习和数据科学包,Numpy包支持在多维数据上的数学运算,提供数据结构以及相应高效的处理函数,很多更高级的扩展库(包括Scipy、Matplotlib、Pandas等库)都依赖于Numpy库;
2、Scipy包用于科学计算,提供矩阵支持,以及矩阵相关的数值计算模块,其功能包含有最优化、线性代数、积分、插值、拟合、信号处理和图像处理以及其他科学工程中常用的计算;
3、Pandas用于管理数据集,强大、灵活的数据分析和探索工具,其带有丰富的数据处理函数,支持序列分析功能,支持灵活处理缺失数据等;
● Pandas基本的数据结构是Series和DataFrame;
● Series就是序列,类似一维数组;
● DataFrame相当于一张二维的表格,类似二维数组,它的每一列都是一个Series;
● 为了定位Series中的元素,Pandas提供了Index对象,每个Series都会带有一个对应的Index,用来标记不用的元素;
● DataFrame相当于多个带有同样Index的Series的组合(本质是Series的容器);
4、Matplotlib库用于数据可视化,强大的数据可视化工具以及作图库,其主要用于二维绘图,也可以进行简单的三维绘图;
5、Seaborn库是基于Matplotlib的高级可视化库;
6、Sklearn库包含大量机器学习算法的实现,其提供了完善的机器学习工具箱,支持预处理、回归、分类、聚类、降维、预测和模型分析等强大的机器学习库,近乎一半的机器学习和数据科学项目使用该包。

16、引用和对象

对象:Python中,一切皆对象;每个对象由:**标识(“identity”),类型(type),Value(值)**组成;

  • 标识用于唯一标识对象,通常对应于对象在计算机内存中的地址;使用内置函数id(obj)可返回对应obj的标识;
  • 类型用于标识对象存储的”数据”的类型;类型可以限制对象的取值范围以及可执行的操作,可以使用type(obj)获得对象的所属类型;
  • 值表示对象存储的数据的信息,使用print(obj)可以直接打印出值;
  • 对象的本质就是: 一个内存块,拥有特定的值,支持特定类型的相关操作;
  • 对象位于:堆内存;

引用:在Python中,变量也成为:对象的引用;因为,变量存储的就是对象的地址;变量通过地址引用了”对象”;

变量位于:栈内存;

17、单例模式

单例模式(Singleton Pattern)是一种常用的软件设计模式,该模式的主要目的是确保某一个类只有一个实例存在。当你希望在整个系统中,某个类只能出现一个实例时,单例对象就能派上用场。

比如,某个服务器程序的配置信息存放在一个文件中,客户端通过一个 AppConfig 的类来读取配置文件的信息。如果在程序运行期间,有很多地方都需要使用配置文件的内容,也就是说,很多地方都需要创建 AppConfig 对象的实例,这就导致系统中存在多个 AppConfig 的实例对象,而这样会严重浪费内存资源,尤其是在配置文件内容很多的情况下。事实上,类似 AppConfig 这样的类,我们希望在程序运行期间只存在一个实例对象。

5分钟学习23种设计模式_识时务者-HJJ的博客-CSDN博客

二、Java

基本数据类型(8种):byte、short、int、long、float、double、boolean、char

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Qq1XwtkC-1661944950493)(C:\Users\13515\AppData\Roaming\Typora\typora-user-images\1661779733531.png)]

1、Java操作字符串的类有哪些?

1661779994974
  • String:属于引用类型(对象),值不可变

String声明的是不可变的对象,每次操作都会生成新的String对象。然后将指针指向新的String对象,而StringBuilder、StringBuild可以在原有对象的基础上进行操作,所以在频繁修改字符串内容的情况下最好不要使用String。

  • StringBuilder: 可变字符序列、线程安全、效率低

  • StringBuffer: 可变字符序列、线程不安全、效率高

  • StringBuffer:可变字符序列、线程安全、效率低

  • StringBuilder:可变字符序列、线程不安全、效率高

2、static的用法和作用?

static关键字表明一个成员变量是成员方法可以在没有所属类的实例变量的情况下被访问。java中static方法不能被覆盖。

1661780247307

3、HashMap和HashTable的区别?底层实现有什么区别吗?

区别:

  • 继承的父类不同

    • HashMap继承自AbstractMap类。但二者都实现了Map接口;
    • Hashtable继承自Dictionary类,Dictionary类是一个已经被废弃的类(见其源码中的注释)。父类都被废弃,自然而然也没人用它的子类Hashtable了。
  • **线程安全:**HashMap线程不安全,HashTable线程安全

  • 包含的contains()不同

    • HashMap是没有contains方法的,而包括containsValue和containsKey方法;
    • hashtable则保留了contains方法,效果同containsValue,还包括containsValue和containsKey方法。
  • 是否允许null值

    • Hashmap是允许key和value为null值的,用containsValue和containsKey方法判断是否包含对应键值对;
    • HashTable键值对都不能为空,否则包空指针异常。
  • 扩容方式不同(容量不够)

    ①扩容;
    ②rehash

    • 这里HashMap和HashTable都会会重新计算hash值,但计算方式就不同了;
    • HashMap 哈希扩容必须要求为原容量的2倍,而且一定是2的幂次倍扩容结果,而且每次扩容时,原来数组中的元素依次重新计算存放位置,并重新插入;
    • 而Hashtable扩容为原容量2倍加1;
  • 解决hash冲突方式不同(地址冲突)

    • hashtable:都是以链表方式存储

    • hashmap

      • jdk8以前:链地址法,查找时间复杂度慢慢变高;

        在这里插入图片描述
      • jdk8:冲突数量小于8,以链表方式解决冲突;冲突数量大于等于8,将冲突的Entry转换为红黑树进行存储;而当冲突数量小于6,又转化为链表存储。

4、Java的内存管理机制

java内存模型(JVM)将虚拟机分为5大区域:程序计数器、虚拟机栈、本地方法栈、java堆、方法区

**程序计数器:**线程私有,用于记录当前虚拟机正在执行的线程指令地址

**虚拟机栈:**线程私有,每个方法执行时都会创建一个栈帧,用于存储局部变量表、操作数、动态链表和方法返回等信息,当线程请求的栈深度超过了虚拟机允许的最大深度时,就会抛出StackOverFlowError

**本地方法栈:**线程私有,保存的是native方法的信息,当一个jvm创建的线程调用native方法后,jvm不会在虚拟机栈中为该线程创建栈帧,而是简单的动态链接并直接调用该方法

**堆:**线程共享的一块内存,几乎所有对象的实例和数组都要在堆上分配内存,因此该区域经常发生垃圾回收的操作

**方法区:**存放已被加载的类信息、常量、静态变量、即时编译器编译后的代码数据

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Pu7mNr0h-1661944950494)(C:\Users\13515\AppData\Roaming\Typora\typora-user-images\1661780885808.png)]

5、ArrayList和LinkedList的异同点

  • **是否保证线程安全:**二者都不是同步的,都不保证线程安全
  • 底层数据结构:ArrayList底层使用Object数组,LinkedList底层使用的是双向循环链表结构
  • 插入和删除是否受元素的位置的影响:ArrayList采用数组存储,所以插入和删除元素的时间复杂度收到元素位置的影响;LinkedList采用链表存储,删除和插入不受元素位置影响
  • **是否支持快速随机访问:**LinkedList不支持高效的随机元素访问,ArrayList实现了RandmoAccess接口,所以有随机访问功能,即通过元素的序号快速获取元素对象
  • 内存空间占用:ArrayList的空间浪费主要体现在list列表的结尾会预留一定的容量空间,而LinkedList的空间浪费体现在它的每一个元素都要消耗比ArrayList更多的空间(因为要存档直接后继和直接前驱以及数据)

6、什么是反射?

定义

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

优缺点

优点 :能够运行时动态获取类的实例,提高灵活性;可与动态编译结合

缺点:使用反射性能较低,需要解析字节码,将内存中的对象进行解析。

如何获取反射中的class对象

1.class.forName(‘com.mysql.jdbc.Driver.class’);

2.类名.class //只适合在编译前就知道操作的class

3.对象名.getClass()

4.如果是基本类型的包装类,可以调用包装类的Type属性来获得该包装类的Class对象

反射使用的步骤

1、获取想要操作类的Class对象,这是反射的核心,通过Class对象我们可以任意调用类的方法

2、调用Class类中的方法,这就是反射的使用阶段

3、使用反射API来操作这些信息

​ 反射API:用来生成JVM中的类、接口或对象的信息

7、举例说明继承、封装、多态

封装:封装就是将客观的事物抽象成类,类中存在属于这个类的属性和方法。
继承:继承就是把父对象继承过来,这样子类就存在了父类的操作方法,java是单继承,就是只能继承一个父对象。
多态:多态就是程序中允许出现重名现象,java实现多态的方式有方法重载和成员变量覆盖两种形式。

8、wait()和sleep()的异同点

相同:二者都可以暂停线程的执行

不同:

  • sleep是Thread的静态方法,当前线程将睡眠n毫秒,线程进入阻塞状态,当睡眠时间到就会解除阻塞进入可运行状态。
  • wait是Object的方法,必须和synchronized关键字一起使用,线程进入阻塞状态,当notify或者notifyall被调用后,会解除阻塞,但是只有重新占用互斥锁之后才会进入可运行状态。
  • sleep方法没有释放锁,而wait方法释放了锁
  • sleep通常被用于暂停执行,而wait用于线程间交互/通信
  • sleep方法执行完成后,线程会自动苏醒,或者可以使用wait(long timeout)超时后线程会自动苏醒。wait方法被调用后,线程不会自动苏醒,需要别的线程调用同一个对象上的notify()或者notifyAll()方法

补充:Thread类中的yield方法也可以暂停当前正在执行的线程对象,让其他有相同优先级的线程执行。它是一个静态方法而且只保证当前线程放弃cpu占用而不能保证其他线程一定能占用cpu,执行yield()线程可能在进入到暂停状态后马上又被执行。

9、线程和进程有何区别?

进程

  • 进程是系统中正在运行的一个程序,程序一旦运行就是进程;
  • 进程可以看成程序执行的一个实例。进程是系统资源分配的独立实体,每个进程都拥有独立的地址空间。一个进程无法访问另一个进程的变量和数据结构,如果想让一个进程访问另一个进程的资源,需要使用进程间通信,比如管道,文件,套接字等;
  • 一个进程可以拥有多个线程,每个线程使用其所属进程的栈空间。线程与进程的一个主要区别是,统一进程内的一个主要区别是,同一进程内的多个线程会共享部分状态,多个线程可以读写同一块内存(一个进程无法直接访问另一进程的内存)。同时,每个线程还拥有自己的寄存器和栈,其他线程可以读写这些栈内存。

线程

  • 线程是进程的一个实体,是进程的一条执行路径;

  • 线程是进程的一个特定执行路径。当一个线程修改了进程的资源,它的兄弟线程可以立即看到这种变化。

二者区别:

1.地址空间和其他资源(如打开文件):进程间相互独立,同一进程的各线程间共享。某进程内的线程在其他进程内不可见。

2.通信:进程间通信IPC(管道,信号量,共享内存,消息队列),线程间可以直接独写进程数据段(如全局变量)来进程通信——需要进程同步和互斥手段的辅助,以保证数据的一致性。

3.调度和切换:线程上下文切换比进程上下文切换快得多。

4.在多线程OS中,进程不是一个可执行的实体。

10、如何实现多线程?

1.实现继承Thread类

步骤:

  • 定义一个类去继承Thread类,比如ThreadDemo
  • 重写run()方法
  • 在测试类中创建ThreadDemo类的对象
  • 启动线程

2.实现Runnable接口

步骤:

  • 定义一个类,实现Runnable接口,比如RunnableDemo类
  • 重写run()方法
  • 创建测试类,并创建RunnableDemo类对象
  • 创建Thread对象,将RunnableDeme类对象作为构造方法的参数传进去
  • 启动线程

与第一种方式看起来其实区别不大,就是实现和继承的区别,还有创建线程时需要将那个实现了Runnable接口的对象传入Thread中当构造方法的参数

3.实现Callable接口

步骤:

  • 定义一个类实现Callable接口,并指定返回值类型,比如CallableDemo
  • 重写call()方法
  • 创建测试类,创建CallableDemo对象
  • 创建Future的实现类FutureTask对象,并将CallableDemo对象作为构造方法的参数传进去
  • 创建Thread类的对象,将FutureTask对象作为构造方法的参数传进去
  • 启动线程
  • 可以通过get方法获取线程结束后的结果

这个跟之前的不同之处就是有个返回值,然后创建时有所不同。

补充:Python和Java的区别

  • python 跟 java 一样时强类型语言,也就是说它不会根据环境变化自动改变数据类型。
  • python 是动态语言,而 java 是静态语言。也就是说 python 在编程时,永远不用给任何变量指定数据类型,而 java 写程序时必须声明所有变量的数据类型。
  • python 的模块类似于 java 的 class,不过python模块导入会执行 代码的内容,而 java 不会 python 与 java 的执行方式还是蛮像的,都是将源码编译成 byte code 然后交给相应的虚拟机去执行。
  • Python为了优化速度,避免为整数频繁申请和销毁内存空间,使用了小整数对象池。对小整数的定义是 [-5, 256] 这些整数对象是提前建立好的,不会被垃圾回收。在这个范围内所有的整数都只会被建立一次 与 java 类似,java 叫常量池,[-128,127],通过 IntegerCache 来实现的 ( Integer [-128,127) 大整数池: python为了避免创建大整数浪费的内存空间和时间,将创建过的大整数加入
  • 大整数池:python中大整数池,默认大整数池里面为空,每一个py程序都有一个大整数池。使用大整数时如果大整数池里不存在该整数的话,会新建一个大整数对象。下次使用大整数时直接使用大整数池里的对象,而不是创建新的对象 。终端是每次执行一次,所以每次的大整数都重新创建,而在pycharm中,每次运行是所有代码都加载都内存中,属于一个整体,所以。这个时候会有一个大整数对象池,即处于一个代码块的大整数是同一个对象。c1 和d1 处于一个代码块,而c1.b和c2.b分别有自己的代码块,所以不相等。 类似于 java 的 字符串常量池,java 不一样,基本数据类型在同一个 jvm 中都会重用。
  • 如果是其他普通类型对象的新建,python会请求内存,申请内存 。当n1的引用指向其他对象时,原有对象的引用计数会自动减1,没有被引用的对象会立即回收( 引用计数法 )。与 java 类似,但 java 不是通过引用计数来回收垃圾的,而是通过 到 GCROOT 的路径通不通来回收垃圾的 ( 可达性分析法 )。
  • python 中有全局变量,而 java 中没有。
  • python引用变量的顺序: Local ->Enclosing ->Global ->Built-in ,与 java 一样,就近原则。
  • Python 中只有模块(module),类(class)以及函数(def、lambda)才会引入新的作用域,其它的代码块(如 if/elif/else/、try/except、for/while等)是不会引入新的作用域的,也就是说这些语句内定义的变量,外部也可以访问, 与 java 类似。
  • python中的字典 key 不能是可变的,可变的会报错,而java中没有此限制,虽然说可能不应该以可变对象为 key。
  • python 的序列( list )、字典( dict )、集合( set ),都可以是混合类型。
  • python 的函数在一定的程序上可以类比于 java 的方法,但函数是不同于方法的。
  • Python 函数的 return 语句可以返回任意类型,也就是说 Python 的函数并没有固定的返回类型,符合动态语言的标识,而java 只能返回特定的类型 Python 函数的参数可以通过关键字指定,而 java 方法不可以。
  • Python 函数有默认参数,而 java方法 没有。
  • 当我们在函数中引用一个变量时,Python 将隐式地默认该变量为全局变量。但是,一旦变量在没有 global关键字修饰的情况下进行了修改操作,Python 会将其作为局部变量处理,并在外部作用域中隐藏任何类似命名的变量。
  • python 的函数定义也可以嵌套,而 java 不可以。
  • python 中的 模块( module ) 其实就是python源文件,package + module 构成了 Python 中的依赖,与 java 类似。

三、Linux

1、ls命令

就是 list 的缩写,通过 ls 命令不仅可以查看 linux 文件夹包含的文件,而且可以查看文件权限(包括目录、文件夹、文件权限)、查看目录信息等等。

2、cd 命令

cd [目录名]
切换当前目录至 dirName。

3、pwd 命令

pwd 命令用于查看当前工作目录路径。

4、mkdir 命令

用于创建文件夹。

5、rm 命令

删除一个目录中的一个或多个文件或目录,如果没有使用 -r 选项,则 rm 不会删除目录。如果使用 rm 来删除文件,通常仍可以将该文件恢复原状。

6、rmdir 命令

从一个目录中删除一个或多个子目录项,删除某目录时也必须具有对其父目录的写权限。
注意:不能删除非空目录。

7、mv 命令

移动文件或修改文件名,根据第二参数类型(如目录,则移动文件;如为文件则重命令该文件)。
当第二个参数为目录时,第一个参数可以是多个以空格分隔的文件或目录,然后移动第一个参数指定的多个文件到第二个参数指定的目录中。

8、cp 命令

将源文件复制至目标文件,或将多个源文件复制至目标目录。
注意:命令行复制,如果目标文件已经存在会提示是否覆盖,而在 shell 脚本中,如果不加 -i 参数,则不会提示,而是直接覆盖!

9、cat 命令

  • 一次显示整个文件: cat filename
  • 从键盘创建一个文件: cat > filename 只能创建新文件,不能编辑已有文件。
  • 将几个文件合并为一个文件: cat file1 file2 > file

10、more 命令

功能类似于 cat, more 会以一页一页的显示方便使用者逐页阅读,而最基本的指令就是按空白键(space)就往下一页显示,按 b 键就会往回(back)一页显示。

11、less 命令

less 与 more 类似,但使用 less 可以随意浏览文件,而 more 仅能向前移动,却不能向后移动,而且 less 在查看之前不会加载整个文件。

12、head 命令

head 用来显示档案的开头至标准输出中,默认 head 命令打印其相应文件的开头 10 行。

13、tail 命令

用于显示指定文件末尾内容,不指定文件时,作为输入信息进行处理。常用查看日志文件。

14、find 命令

用于在文件树中查找文件,并作出相应的处理。

15、chmod 命令

用于改变 linux 系统文件或目录的访问权限。用它控制文件或目录的访问权限。该命令有两种用法。一种是包含字母和操作符表达式的文字设定法;另一种是包含数字的数字设定法。
每一文件或目录的访问权限都有三组,每组用三位表示,分别为文件属主的读、写和执行权限;与属主同组的用户的读、写和执行权限;系统中其他用户的读、写和执行权限。

16、grep 命令

强大的文本搜索命令,grep(Global Regular Expression Print) 全局正则表达式搜索。
在一个或多个文件中搜索字符串模板。如果模板包括空格,则必须被引用,模板后的所有字符串被看作文件名。搜索的结果被送到标准输出,不影响原文件内容。

17、查看端口占用

方式1 : lsof 是一个列出当前系统打开文件的工具 —— lsof -i:端口号

tip:需要root用户权限来执行,否则什么都看不到

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jPiHCfXS-1661944950495)(C:\Users\13515\AppData\Roaming\Typora\typora-user-images\1661922487717.png)]

方式2 : netstat 用于显示tcp、udp的端口和进程等相关情况 —— netstat -tunlp|grep 端口号

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-j4UYIu4W-1661944950495)(C:\Users\13515\AppData\Roaming\Typora\typora-user-images\1661922599678.png)]

如果想查看进程更多信息,使用 ps -ef|grep 进程PID

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-F9wBMLRq-1661944950496)(C:\Users\13515\AppData\Roaming\Typora\typora-user-images\1661922693980.png)]

杀死进程——kill -9 PID 与kill的区别:前者是强制杀死,无条件终止;后者是告诉进程请自行停止

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-i9bPBO8r-1661944950496)(C:\Users\13515\AppData\Roaming\Typora\typora-user-images\1661922729900.png)]

18、统计某个文件夹下.java的文件个数和代码总行数

wc命令,可以打印出每个文件和总文件的行数、字数、字节数。

命令语法:wc [选项] 文件

该命令选项参数如下:

-c 统计字节数

-l 统计行数

-w 统计字数

-m 统计字符数

wc -l : 统计输出信息的行数,统计结果就是输出信息的行数,一行信息对应一个文件,所以就是文件的个数;

wc -l filename 输出 filename 的行数

wc -c filename 输出 filename 的字节数

wc -m filename 输出 filename 的字符数

wc -w filename 输出 filename 的单词数

wc -L filename 输出 filename 文件里最长的那一行是多少个字符数

如需了解更多的 wc 命令的详情,请输入命令 wc --help 查看。

19、统计文件中出现次数最多的前10个单词

cat words.txt|sort|uniq -c|sort -k1,1nr|head -10

四、基本素质

1、对测试和测试开发的理解

聊一聊我对测试开发的看法_小菠萝测试笔记的博客-CSDN博客

2、职业规划

【1~3年】提高测试技能、深入了解测试过程

  • 熟悉整个测试过程及产品业务领域,学习和掌握自动测试工具,学习测试自动化编程技术;开发和执行测试脚本,承担系统测试实施任务;学习编程语言、操作系统、网络与数据库方面的技能。

  • 深入了解测试过程,掌握测试过程设计及改进,参与软件工作产品的同行评审;进一步了解产品业务领域,改进测试自动化编程技术,能指导初级测试工程师;加强编程语言、操作系统、网络与数据库方面的技能。

【4~6年】测试组织工作、做好技术管理

  • 组织工作:管理1~3名测试工程师,担任任务估算、管理及进度控制;进一步培养在软件项目管理及支持工具方面的技能。
  • 技术管理:管理4~8名测试工程师,提高任务估算、管理及进度控制能力,完成测试规划冰制定测试计划;研究测试的技术手段,保持使用项目指导及支持工具的技能;用大量的时间为其他测试工程师提供技术及过程方面的指导;开始与客户打交道并做演示推介。

【7~10年】测试管理

  • 管理8名以上测试工程师,负责一个或多个项目的测试工作,与客户打交道并做演示推介;保持使用项目管理及支持工具的技能。

3、工作优势/核心竞争力

  • 综合能力

    • 沟通能力

    • 学习能力

    • 开发能力(数据结构,项目开发经历)

    • 文档能力(测试用例设计能力)

      如何提高测试用例设计的能力?
      1,掌握设计测试用例的方法
      2,积累,总结
      3,阅读好的测试用例设计案例

  • 探索性思维

    • 思维不受条条框框束缚,具有发散性思维,能够结合实际来思考问题。
  • 兴趣&&责任感/有一定的压力

    责任感是任何工作的都需要的,对于测试工作者而言:
    测试往往是产品质量的最后个把关者;由于测试工作成效很难衡量,测试用例执行、bug数目的多少都无法说明产品的质量是否合格;所以,责任感是最重要的测试必备素质之一。
    压力,测试工作者,特别是属于互联网行业需要能够抗住各种压力
    此时兴趣就尤为重要,兴趣可以支持我们对工作热情,让我们在这条路上走的更远

4、如何学习一门新技术?

如何学习一门新技术,我觉得对我而言,新技术可以分成两种,一种是能和自己之前学过的东西有关联的新技术,一种是一个全新的领域,在这方面基础为 0 的。

**举例:**比如我在学 Java 的过程中,学到 Redis 这块,这种技术就是第一种。首先,我会找它和 Sql 之间的联系与区别。从这些方面先有个宏观的认识,并且尽量在脑子里对这些有个大致的概念,能记录下来这些 tips 更好。这样在后面深入了解它的时候,看到相关方面的知识,能联想到之前的 tips,加深自己的理解。

对于学习方式来说,主要有两种,一种是通过书本,一种是通过 B 站视频。

  • 先找学习路线,画思维导图,明确知识点主次

  • 然后搜集一下官方文档或者B站播放量高且讲课风格适合自己的up主;

  • 列大纲,梳理知识点,并且通过文档的方式记录下来;

  • 学完课程后,要及时复盘自己的笔记;

  • 实践,尝试代码。

    技术的迭代是程序员毕生主动或者被动地学习,在日常工作的同时不可避免的需要不停地学习新技术,可以在闲暇之余每天进步一点,这样,在运用之时也就起到了笨鸟先飞的作用吧!

5、回答问题的思路和角度

STAR 法则四要素:

  • Situation:事情是在什么情况下发生,基于一个怎样的背景;
  • Task:你是如何明确你的任务的;
  • Action:针对这样的情况分析,你采用了什么行动方式,具体做了哪些工作内容;
  • Result:结果怎样,带来了什么价值,在整个过程中你学到了什么,有什么新的体会。

五、测试面试题

1、如何判断前后端bug?

  • 界面相关,排版错乱,文案错误等问题,大都属于前端bug

    • 出现样式的问题基本都是CSS的bug
    • 出现文本的问题基本都是html的bug
    • 出现交互类的问题基本都是JS的bug
  • 功能相关,抓包分析,从接口请求url,参数,接口响应来分析

    • 未发送请求,就属于前端bug
    • 接口请求url错误,传参错误,就属于前端bug
    • 接口返回数据错误,就属于后端bug
  • 性能相关

    • 例如页面加载慢或提交表单慢,一直pending,抓包查看请求耗时,如果耗时长,那就属于后端bug
  • 安全相关

    • 越权。可以分为水平越权和垂直越权,以下两个例子都属于后端Bug。
      • 水平越权的例子:在业务系统中,本来用户A只能对自己的个人信息进行增删改查,但是通过抓包,修改用户id(一般用户id都是递增的),可以获取到其他人的个人信息,或者账号A将自己的个人信息页面通过浏览器发送给用户B,用户B登录系统后可以看到用户A的信息,这就是水平越权了
      • 垂直越权的例子:在业务系统中,本来用户A对某条记录只有查看的权限,但是通过抓包,可以对记录进行修改,这就是垂直越权了
  • 前后端均有问题

    • 例如对于字段有效性的校验等,前后端均需要校验,因此属于前后端共同的bug

2、软件测试的目的

  • 发现被测对象与用户需求之间的差异,即缺陷。
  • 通过测试活动发现并解决缺陷,增加人们对软件质量的信心。
  • 通过测试活动了解被测对象的质量状况,为决策提供数据依据。
  • 通过测试活动积累经验,预防缺陷出现,降低产品失败风险。

3、软件测试的原则

  • 所有测试的标准都是建立在用户需求之上
  • 始终保持“质量第一”的觉悟,当时间和质量冲突时,时间要服从质量
  • 需求阶段应定义清楚产品的质量标准
  • 软件项目一启动,软件测试就已经开始,而不是等程序写完,才开始进行测试
  • 第三方进行测试会更客观,更有效
  • 软件测试计划是做好软件测试工作的前提
  • 测试用例是设计出来的,不是写出来的
  • 对发现错误较多的程序段,应进行更深入的测试

4、测试人员在软件开发过程中的任务是什么?

  • 参与需求评审,指出需求缺陷,理解需求(即本次要做什么,并对测试内容有一个初步规划)
  • 制定测试计划。测试工时排期,任务拆分等
  • 根据需求文档,进行测试点拆分,测试用例设计
  • 进行测试用例评审,保证测试范围。与产品,开发等对测试内容达成一致
  • 参与开发人员组织的需求/技术反讲,数据库评审,代码评审等。从开发角度理解需求实现方式,数据库交互等等,对自己的测试范围进行查漏补缺
  • 提测阶段,最好让开发人员演示主功能,保证版本提测质量。
  • 提测后 执行测试用例 进行系统测试 提交缺陷
  • 回归测试,回归缺陷,流程
  • 测试release测试(冻结环境测试)
  • 版本上线后,正式环境测试
  • 版本上线后,跟进线上问题,对线上问题进行复现,并修复后上线,验证缺陷是否修复以及影响范围
  • 协助开发 尽量找出全部的bug降低上线后的隐患
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值