获取类对象(Retrieving Class Objects)

本文深入介绍了Java反射机制的基础知识,包括如何通过不同方法获取Class对象,如使用对象实例、类名称、静态方法及特殊语法等。同时,还探讨了如何利用反射API获取类的详细信息。

   所有反射操作的入口是java.lang.Class.包括异常类java.lang.reflect.ReflectPermission,java.lang.reflect包中的所有类都没有公有构造函数。为了获得这些类,需要调用Class类中合适的方法。有几种方式可以获取一个Class,取决于代码是否有相应实例对象、类名称、类型或者一个存在的Class。

Object.getClass()
   如果一个对象的实例是可用的,那么获取它的类类型最简单的方法是调用Object.getClass().当然,这种方法仅适用于继承Object类的引用类型。例如:

Class = "foo".getClass(); 

返回的类类型是String

Class c = System.console().getCLass();

这是一个由静态方法System.console()返回的和虚拟机关联的唯一控制台,getClass()方法返回的值和java.io.Console类型是一致的

enum E{ A,B}
Class c = A.getClass();

A是枚举E的一个实例,那么getClass()方法返回的类型和枚举类型E是一致的。

byte[] bytes = new byte[1024];
Class c = bytes.getClass();

由于数组都是对象,同样可以调用数组实例的getClass()方法,它返回的类类型和数组元素类型byte是一致的。

import java.util.HashSet;
import java.util.Set;
Set<String> s = new HashSet<String>();
Class c = s.getClass();

在这个例子中,java.util.Set是一个接口指向java.util.HashSet类型的实例对象,getClass()方法返回的值和java.util.HashSet类型是一致的。

The .class Syntax
   如果类型是可以获得的,但是没有这类型的实例,那么是可以通过这类型名称后加”.class”方式来获得这个类型。这也是获取基本数据类型的类类型的最简单方法。

boolean b ;
Class c = b.getClass();//error
Class c = boolean.class;

注意,语句boolean.getClass()会产生一个编译时的错误,因为boolean是一个基本数据类型并且不能够被引用。这个.class语句返回类类型和类型boolean是一致的。

Class c = java.io.PrintStream.class;

变量c将会和java.io.PrintStream类型一致的。

Class c = int[][].class;

这个.class语句可能被用于获取一个和多维数据元素类型一致的类类型。

Class.forName()
   如果一个类的全称是可以获得的,那么可以使用静态方法Class.forName()来获取相应的类类型,这个不能用于基本数据类型。这用法对于数据类型的名称被描述成Class.getName(),这个则适用于引用和基本数据类型。

Class c = Class.forName("com.duke.MyLocaleServiceProvider");

这个语句会用已给定的全名创建一个Class对象。

Class cDoubleArray = Class.forName("[D");
Class cStringArray = Class.forName("[[Ljava.lang.String;");

变量cDoubleArray将会是和数组元素类型double一样的类型(和double[].class相似);变量cStringArray将会是和二维数组元素类型String一致(类似String[][].class)

TYPE Field for Primitive Type Wrappers
   对于基本数据类型,.class方法获取Class对象是一个更加方便和首选的方式,然而,还有另外一种方法可以获取类类型,每个基本数据类型和void都有一个相应的封装类型,存在于包java.lang,封装类型被用于将基本类型封装成引用类型。每个封装类包含一个字段,名称为TYPE,这个相当于Class,对于被封装的基本数据类型。

Class c = Double.TYPE;

类java.lang.Double被用于封装基本数据类型double,无论什么时候需要一个对象,Double.TYPE和double.class的值是一样的。

Class c = Void.TYPE;

Void.TYPE相当于void.class

Methods that Return Classes
   有一些反射APIs但仅当已经直接或者间接的获取到Class对象可以访问到来返回类对象。

Class.getSuperClass()
   返回给定类的父类

Class c = javax.swing.JButton.class.getSuperClass();

   javax.swing.JButton的父类是javax.swing.AbstractButton

Class.getClasses()
   返回成员类包括继承的成员的所有的公有类,接口和枚举。

Class<?>[] c = Character.class.getClasses();

   Character类包含两个成员类Character.Subset和Character.UnicodeBlock.

Class.getDeclaredClasses()
   返回类中明确声明的接口,枚举。

Class<?>[] c = Character.class.getDeclaredClasses();

   Character类包含两个公有成员类Character.Subset、Character.UnicodeBlock和一个私有类Character.CharacterCache.

Class.getDeclaringClass()
java.lang.reflect.Field.getDeclaringClass()
java.lang.reflect.Method.getDeclaringClass()
java.lang.reflect.Constructor.getDeclaringClass()
   返回这些被声明的成员类型,匿名类将没有声明类型但是包含一个封装类型。

import java.lang.reflect.Field;
Field f = System.class.getField("out");
Class c = f.getDeclaringClass();

   字段在System类中声明。

public class MyClass{
    static Object o = new Object(){
        public void m();
    }
    static class<c> = o.getClass().getEnclosingClass();
}

   这个匿名类o的类型是null。

Class.getEnclosingClass()
   返回类对象的立即封闭类

Class c = Thread.State.class.getEnclosingClass();

   枚举Thread.State的封闭类是Thread。

public class MyClass{
    static Object o = new Object(){
        public void m(){}
    }
    static Class<c> = o.getClass().getEnclosingClass();
}

   引用对象o的匿名类是MyClass封闭类。

<think>好的,用户想了解Python类的基本概念和核心用法,需要一个完整的教程。首先,我需要回忆Python中类的核心知识点,比如类定义、属性、方法、继承等。用户可能刚接触面向对象编程,所以需要从基础讲起,结构清晰,逐步深入。 首先,类的基本概念,包括类和实例的区别。然后,类的定义语法,使用class关键字。接下来是构造函数__init__,用来初始化实例属性。属性和方法的分类,比如实例属性、类属性,实例方法、类方法、静态方法,这些都需要详细说明,并给出示例代码。 然后,继承和多态是OOP的重要概念,要解释如何创建子类,重写方法,以及多态的表现。可能需要对比其他语言中的继承机制,比如Python支持多重继承,但这里先介绍单继承,避免复杂化。 封装部分,需要说明访问控制,Python中没有严格的私有变量,但可以通过下划线约定来实现。这部分需要强调命名约定而非强制限制。 最后,应用场景和标准库中的例子可以增加实用性,比如引用用户提到的标准库中的类,比如datetime.date,这样用户能联系实际。同时,常见问题解答能帮助用户避免典型错误,比如忘记self参数。 要确保所有代码示例正确,符合Python语法,并且注释清晰。引用用户提供的参考信息,比如标准库的描述,在适当的地方添加引用标识。另外,按照用户要求,行内公式用$...$,独立公式用$$...$$,但当前问题可能较少涉及数学公式,不过如果有计算相关的内容,比如类的属性计算,可能需要用LaTeX表达。 需要检查是否有遗漏的核心概念,比如特殊方法(魔术方法)、属性装饰器、多态的具体例子等。确保教程结构合理,由浅入深,示例代码能逐层展示各个概念。最后,生成相关问题,帮助用户进一步学习,比如类与实例的区别、方法类型的选择、继承的注意事项等。</think># Python类(Class)完整教程 ## 一、基本概念 1. **类与对象** - 类(Class)是创建对象的蓝图,描述对象的**属性**和**行为** - 对象(Object)是类的具体实例,每个对象拥有独立的内存空间 - 例如:`str`类是字符串模板,`"hello"`是具体实例 2. **面向对象三大特性** - 封装:隐藏内部实现细节,通过方法暴露功能 - 继承:子类复用父类特性 - 多态:不同对象对相同方法做出不同响应 $$面向对象 = 对象 + 类 + 继承 + 消息通信$$ ## 二、核心语法 ### 1. 类定义 ```python class Dog: species = 'Canis familiaris' # 类属性(所有实例共享) def __init__(self, name, age): # 构造方法 self.name = name # 实例属性 self.age = age def bark(self): # 实例方法 print(f"{self.name} says woof!") ``` ### 2. 创建实例 ```python my_dog = Dog('Buddy', 3) print(my_dog.name) # 输出: Buddy my_dog.bark() # 输出: Buddy says woof! ``` ### 3. 方法类型 | 类型 | 装饰器 | 参数要求 | 调用方式 | |-----------|---------|-------------|---------------| | 实例方法 | 无 | 必须包含self | 通过对象调用 | | 类方法 | @classmethod | 必须包含cls | 通过类或对象调用 | | 静态方法 | @staticmethod | 无特殊参数要求 | 通过类或对象调用 | ```python class MyClass: @classmethod def class_method(cls): print(f"Called class method of {cls}") @staticmethod def static_method(): print("Called static method") ``` ### 4. 继承 ```python class GoldenRetriever(Dog): # 继承Dog类 def bark(self): # 方法重写 print(f"{self.name} says gentle woof!") def special_skill(self): # 扩展新方法 print("Retrieving objects!") ``` ## 三、高级特性 ### 1. 封装控制 - 单下划线`_var`:约定为受保护成员(非强制) - 双下划线`__var`:名称修饰(Name Mangling)实现伪私有 ```python class BankAccount: def __init__(self): self.__balance = 0 # 伪私有属性 def deposit(self, amount): self.__balance += amount ``` ### 2. 特殊方法 通过实现魔术方法定制类行为: ```python class Vector: def __init__(self, x, y): self.x = x self.y = y def __add__(self, other): # 实现向量加法 return Vector(self.x + other.x, self.y + other.y) def __str__(self): # 定义打印格式 return f"Vector({self.x}, {self.y})" ``` ## 四、标准库应用 Python标准库大量使用类实现核心功能: ```python from datetime import date today = date.today() # date类的静态方法[^1] print(today.year) # 访问实例属性 ``` ## 五、最佳实践 1. **SOLID原则** - 单一职责:一个类只做一件事 - 开放封闭:对扩展开放,对修改关闭 - 里氏替换:子类可替换父类 - 接口隔离:专用接口优于通用接口 - 依赖倒置:依赖抽象而非具体实现 2. **常见问题** ```python # 错误示例:忘记self参数 class Test: def method(): # 缺少self参数 print("Error!") # 正确写法 class Test: def method(self): print("Correct!") ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值