编程语言面试题(一)
1、Java反射机制的作用是什么?
Java反射(Reflection)是Java语言的一个强大特性,它允许程序在运行时动态地获取类的信息并操作类或对象的属性、方法和构造器。Java反射机制的主要作用是为程序提供运行时动态操作类或对象的能力,打破了传统编程中"编译时确定"的限制。
反射机制的详细作用 | |
运行时获取类信息 | 动态获取类的完整结构:包括类名、父类、接口、修饰符等 |
获取类的成员信息:字段(属性)、方法、构造器等详细信息 | |
获取泛型信息:可以获取类、方法、字段的泛型类型参数 | |
获取注解信息:读取类、方法、字段上的注解及其属性值 | |
运行时操作类或对象 | 动态创建对象:即使编译时不知道具体类名 |
动态调用方法:可以调用任意方法,包括私有方法(需设置accessible) | |
动态访问/修改字段值:可以读写任意字段,包括私有字段 | |
突破访问限制 | 访问私有成员:通过setAccessible(true)可以突破private限制 |
调用私有方法:可以调用类的私有方法 | |
操作final字段:可以修改final修饰的字段值(但有风险) | |
动态代理 | 实现AOP编程:如Spring的@Transactional注解就是通过动态代理实现的 |
接口代理:为接口动态生成实现类 | |
框架开发的核心支撑 | 依赖注入:如Spring通过反射实现IoC容器 |
ORM框架:如Hibernate/MyBatis通过反射实现对象-关系映射 | |
序列化/反序列化:如Jackson/Gson通过反射实现JSON转换 | |
单元测试:测试框架通过反射调用测试方法 | |
注解处理:运行时处理各种注解 | |
通用工具开发 | 对象拷贝工具:如BeanUtils.copyProperties() |
动态验证工具:运行时验证对象属性 | |
插件系统:动态加载和执行插件 | |
动态类型操作 | 操作数组:动态创建和操作各种类型数组 |
处理不确定类型:编写通用代码处理各种类型对象 |
反射的优缺点 | |
优点 | 缺点 |
提高代码的灵活性和扩展性 可以在运行时动态操作类或对象适合开发通用框架和工具 | 性能开销较大(比直接调用慢) 破坏了封装性(可以访问private成员) 增加了代码复杂度安全问题(可以突破private限制) |
2、反射机制与直接调用函数有什么区别?
由于反射涉及动态解析类型,其性能通常低于直接代码调用。在性能敏感的场景中,应谨慎使用反射或考虑缓存反射操作的结果。
反射是Java语言的一个强大特性,合理使用可以极大增强程序的灵活性,但过度使用也可能带来维护和性能问题。
3、Python中__init__方法的作用是什么?
在 Python 中,__init__
方法是一个特殊的方法,用于在创建类的实例时进行初始化操作。它是类的构造函数(constructor),在对象被实例化时自动调用。
__init__
方法的作用:
- 初始化对象的属性:通常用于给对象的属性赋初始值。
- 执行必要的设置:例如打开文件、建立数据库连接等初始化操作。
- 接受参数:可以在实例化对象时传入参数,用于定制对象的初始状态。
class Person: def __init__(self, name, age): self.name = name # 初始化 name 属性 self.age = age # 初始化 age 属性 # 创建 Person 的实例,自动调用 __init__ person1 = Person("Alice", 30) print(person1.name) # 输出: Alice print(person1.age) # 输出: 30
关键点:
- self 参数:代表类的实例,必须是第一个参数,但调用时不需要手动传递。
- 自动调用:在创建对象时(如 obj = MyClass())自动执行。
- 可以有参数:可以在 __init__ 中定义参数,实例化时传入(如 Person("Alice", 30))。
- 不是必须的:如果不需要初始化,可以不定义 __init__,Python 会提供默认的空实现。
4、Python中初始化方法的区别?
初始化方式 | 适用场景 |
__init__ | 标准初始化方法,用于设置实例属性 |
__new__ | 控制实例创建过程(如单例模式) |
类变量 | 定义所有实例共享的属性 |
默认参数 | 提供可选初始化参数 |
提供替代构造方法(如 from_birth_year) | |
__post_init__ | dataclasses的额外初始化逻辑 |
6、Python中__new__和__init__区别?
__new__
控制实例的创建,__init__
控制实例的初始化
方法 | __new__ | __init__ |
作用 | 创建并返回类的实例(构造方法) | 初始化实例(初始化方法) |
调用时机 | 在__init__之前调用 | 在__new__之后调用 |
返回值 | 必须返回一个实例(通常是cls的实例) | 无返回值(None) |
参数 | cls(类本身) | self(实例本身) |
是否必须 | 通常不需要定义(除非自定义实例创建逻辑) | 可选(但常用于初始化) |
用途 | 单例模式、不可变类型(如str,tuple)子类化 | 初始化实例属性 |
7、什么情况下重写new方法?
1)单例模式(Singleton)
确保一个类只有一个实例,并提供一个全局访问点。
实现方式:在 __new__
中检查是否已存在实例,若存在则返回该实例,否则创建新实例。
class Singleton: _instance = None def __new__(cls, *args, **kwargs): if cls._instance is None: cls._instance = super().__new__(cls) return cls._instance obj1 = Singleton() obj2 = Singleton() print(obj1 is obj2) # True(两个变量指向同一个实例)
2)继承不可变类型(如 str
, tuple
, int
)
不可变类型(immutable)的实例在创建后不能修改,因此需要在 __new__
中控制其创建方式。
class UpperStr(str): def __new__(cls, value): # 在创建实例前修改值 modified_value = value.upper() return super().__new__(cls, modified_value) s = UpperStr("hello") print(s) # "HELLO"(实例化时自动转为大写)
3) 对象池(Object Pooling)
复用已创建的对象以减少资源消耗(如数据库连接、线程池等)。
实现方式:在 __new__
中维护一个对象池,返回已存在的对象而非创建新实例。
class DatabaseConnection: _pool = [] def __new__(cls): if cls._pool: return cls._pool.pop() else: new_conn = super().__new__(cls) new_conn._initialize() # 模拟初始化连接 return new_conn def _initialize(self): print("New connection created") self.is_active = True def close(self): self.is_active = False self.__class__._pool.append(self) # 放回池中 # 使用 conn1 = DatabaseConnection() # 输出: New connection created conn1.close() conn2 = DatabaseConnection() # 无输出,复用 conn1 print(conn1 is conn2) # True
4) 动态修改实例属性(在 __init__
之前)
如果需要在实例创建时动态修改属性(例如根据参数决定实例类型),可以在 __new__
中处理。
class Animal: def __new__(cls, animal_type, *args, **kwargs): if animal_type == "dog": return super().__new__(Dog) elif animal_type == "cat": return super().__new__(Cat) else: return super().__new__(cls) class Dog(Animal): def speak(self): return "Woof!" class Cat(Animal): def speak(self): return "Meow!" pet = Animal("dog") print(pet.speak()) # "Woof!"(实际返回的是 Dog 的实例)
5) 自定义元类(Metaclass)的辅助
在元类编程中,__new__
可以拦截类的创建过程(注意:这里是类的 __new__
,不是实例的 __new__
)。
class UpperAttrMeta(type): def __new__(cls, name, bases, attrs): uppercase_attrs = { k.upper(): v for k, v in attrs.items() } return super().__new__(cls, name, bases, uppercase_attrs) class MyClass(metaclass=UpperAttrMeta): x = 1 print(hasattr(MyClass, "x")) # False print(hasattr(MyClass, "X")) # True(属性名被转为大写)#测试面试##测试#
整理面试过程中的测试问答,常看常新,多多学习!有些问题是从其他人那里转载而来,会在文章下面注明出处,希望大家多多支持~~ 内容目录:https://www.nowcoder.com/discuss/779856598809264128?sourceSSR=users