使用反射,访问私有构造方法,域变量

本文通过一个具体的Java程序示例,详细介绍了如何使用Java反射机制来创建对象实例、修改私有字段值以及调用私有方法等内容。通过反射,可以实现原本无法直接访问的类成员的读写操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

package com.my;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

import static java.lang.System.out;
class A
{
    private int num;
    
    private A()
    {
        num = 0;
        System.out.println("A()");
    }
    
    private A(int i)
    {
        System.out.println("A(int i)");
    }
    
    public void dosth()
    {
        System.out.println("dosth()" + " " + num);
    }
    
    private void dointer()
    {
        out.println("dointer()" );
    }
}

public class Main
{
    //A a;

    public static void main(String[] args) throws Exception
    {
        //A a = new A();
        Constructor<?>[] con = A.class.getDeclaredConstructors();
        
        System.out.println(con[0]);
        System.out.println(con[1]);
        
        con[0].setAccessible(true);        
        A a = (A)con[0].newInstance();
        a.dosth();
        
        con[1].setAccessible(true);        
        A b = (A)con[1].newInstance(1);
        b.dosth();
        
        Field f = A.class.getDeclaredField("num"); 
        f.setAccessible(true);
        f.set(a, 11);
        a.dosth();
        
        Constructor<?> conSingle = A.class.getDeclaredConstructor();
        conSingle.setAccessible(true);
        A c = (A) conSingle.newInstance();
        c.dosth();
        
        Method m = A.class.getDeclaredMethod("dointer");
        m.setAccessible(true);
        m.invoke(a);
        m.invoke(b);
        
        
    }
    
}

<think>在C#中,静态构造方法私有构造方法都是特殊的构造方法,它们各自有不同的用途和调用场景。###1.静态构造方法(静态构造函数)- **定义**:静态构造函数用于初始化类的静态成员。它不能有访问修饰符(默认为私有),也不能带任何参数。- **特点**:-一个类只能有一个静态构造函数。-静态构造函数在创建第一个实例或引用任何静态成员之前自动调用。-不能直接调用静态构造函数。- **用途**:通常用于初始化静态字段,特别是当初始化需要复杂逻辑时。 ####示例代码:```csharppublicclass MyClass{//静态字段public staticintStaticField;//静态构造函数static MyClass(){StaticField =100;Console.WriteLine("静态构造函数被调用");} }class Program{staticvoid Main(){//第一次访问静态成员,触发静态构造函数Console.WriteLine(MyClass.StaticField); //输出:静态构造函数被调用然后输出100}} ```###2.私有构造方法私有构造函数) -**定义**:私有构造函数是一种实例构造函数,用`private`访问修饰符声明。- **特点**:-私有构造函数阻止外部通过`new`关键字创建类的实例。-通常用于单例模式、工厂方法模式或者只包含静态成员的类。 -**用途**:-实现单例模式:确保一个类只有一个实例。-工具类:当类只包含静态方法时,防止实例化。####示例1:单例模式```csharppublicclass Singleton{//静态变量,保存唯一实例privatestatic Singleton_instance;//私有构造函数,防止外部实例化private Singleton() {}//公共静态方法,提供全局访问点public staticSingleton Instance{get{if(_instance== null){_instance= newSingleton();}return_instance;}} }class Program{staticvoid Main(){//获取单例实例Singleton s1 =Singleton.Instance;Singleton s2 =Singleton.Instance;Console.WriteLine(s1== s2);//输出:True}} ```####示例2:工具类(只包含静态成员) ```csharppublicclass Utility{//私有构造函数,防止实例化privateUtility(){ }//静态方法publicstatic voidDoSomething(){Console.WriteLine("执行工具方法");}} classProgram{static voidMain(){//只能通过类名调用静态方法,不能实例化Utility.DoSomething();//Utilityutility= newUtility();//编译错误,因为构造函数是私有的} }``` ###3.静态构造方法私有构造方法的结合使用在某些情况下,我们可能同时使用静态构造函数和私有构造函数。例如,在单例模式中,我们可能使用静态构造函数来初始化单例实例。####示例:使用静态构造函数初始化单例```csharppublic classSingleton{//在静态构造函数中初始化实例privatestatic readonlySingleton _instance =new Singleton();//私有构造函数private Singleton(){Console.WriteLine("实例被创建");}//静态构造函数(可选,用于初始化静态成员)static Singleton(){//这里可以执行其他静态初始化Console.WriteLine("静态构造函数被调用");}publicstatic SingletonInstance =>_instance; }class Program{staticvoid Main(){Console.WriteLine("开始");Singletons =Singleton.Instance; //触发静态构造函数和实例的创建Console.WriteLine("结束");} }``` **输出**: ```开始静态构造函数被调用实例被创建结束```###注意事项:1.**静态构造函数的调用时机**:在第一次使用类之前(创建实例或访问静态成员)自动调用,且只调用一次。2.**私有构造函数的限制**:如果类中只有私有构造函数而没有公共构造函数,那么这个类不能被继承(因为子类构造函数必须调用父类的构造函数,而私有构造函数在子类中不可访问)。 3. **单例模式线程安全**:上面的单例示例在单线程环境下是安全的,但在多线程环境下可能会创建多个实例。为了线程安全,可以使用锁或者使用静态初始化(如上面的示例使用静态字段初始化,因为静态字段的初始化是线程安全的)。 ###线程安全的单例模式(使用锁): ```csharppublicclass ThreadSafeSingleton{privatestatic ThreadSafeSingleton_instance;private staticreadonly object_lock= newobject();privateThreadSafeSingleton(){ }publicstatic ThreadSafeSingletonInstance{get{if (_instance ==null)//第一次检查{lock(_lock){if (_instance ==null)//第二次检查(双重检查锁定){_instance= newThreadSafeSingleton();}}}return_instance;}} }``` ###总结: -**静态构造函数**:用于初始化静态成员,自动调用且只调用一次。 -**私有构造函数**:用于控制实例的创建,常见于单例模式和工具类。 §§相关问题§§: 1.静态构造函数在继承中如何工作?2.如何实现一个线程安全的单例模式?3.在C#中,静态构造函数和静态字段初始化顺序是怎样的? 4.私有构造函数如何影响类的可继承性?</think># C# 中的静态构造方法私有构造方法详解 在 C# 中,静态构造方法私有构造方法是两种特殊类型的构造函数,它们各自有独特的用途和行为。下面我将详细解释它们的用法并提供代码示例。 ## 一、静态构造方法(静态构造函数) ### 定义和特点 静态构造函数用于初始化类的**静态成员**,具有以下特点: - 使用 `static` 关键字修饰 - 不能有访问修饰符(默认为 private) - 不能带参数 - 一个类只能有一个静态构造函数 - 在类首次被访问时自动调用(创建实例或访问静态成员) - 不能被直接调用 ### 使用场景 1. 初始化静态字段或属性 2. 执行只需要执行一次的静态初始化逻辑 3. 初始化静态配置或资源 ### 代码示例 ```csharp using System; class Logger { // 静态字段 private static readonly string LogFilePath; // 静态属性 public static DateTime LastInitialized { get; private set; } // 静态构造函数 static Logger() { LogFilePath = $"logs/{DateTime.Now:yyyyMMdd}.log"; LastInitialized = DateTime.Now; Console.WriteLine($"静态构造函数被调用,日志文件: {LogFilePath}"); } // 静态方法 public static void Log(string message) { Console.WriteLine($"[{DateTime.Now}] {message} - 写入文件: {LogFilePath}"); } } class Program { static void Main() { // 首次访问静态成员时触发静态构造函数 Console.WriteLine($"Logger 最后初始化时间: {Logger.LastInitialized}"); // 再次访问不会触发静态构造函数 Logger.Log("测试日志消息"); /* 输出: 静态构造函数被调用,日志文件: logs/20230815.log Logger 最后初始化时间: 2023-08-15 10:30:45 [2023-08-15 10:30:45] 测试日志消息 - 写入文件: logs/20230815.log */ } } ``` ### 关键点解释 1. **自动调用**:当首次访问 `Logger.LastInitialized` 时,静态构造函数被自动调用 2. **只执行一次**:无论创建多少实例,静态构造函数只执行一次 3. **初始化顺序**:静态字段初始化器在静态构造函数之前执行 4. **线程安全**:.NET 保证静态构造函数只在一个线程中执行一次 ## 二、私有构造方法私有构造函数) ### 定义和特点 私有构造函数用于限制类的实例化,具有以下特点: - 使用 `private` 访问修饰符 - 阻止外部直接使用 `new` 创建实例 - 常用于实现特殊设计模式(如单例、工厂方法等) ### 使用场景 1. 单例模式(确保只有一个实例) 2. 工厂方法模式(通过静态方法创建实例) 3. 工具类(只包含静态方法,无需实例化) 4. 控制对象创建逻辑 ### 代码示例 #### 1. 单例模式实现 ```csharp public class DatabaseConnection { // 静态实例(单例) private static readonly DatabaseConnection _instance = new DatabaseConnection(); // 私有构造函数 private DatabaseConnection() { Console.WriteLine("数据库连接已创建"); } // 公共静态访问点 public static DatabaseConnection Instance => _instance; public void ExecuteQuery(string sql) { Console.WriteLine($"执行查询: {sql}"); } } class Program { static void Main() { // 只能通过 Instance 属性获取单例 var db1 = DatabaseConnection.Instance; var db2 = DatabaseConnection.Instance; db1.ExecuteQuery("SELECT * FROM Users"); Console.WriteLine($"db1 和 db2 是同一个实例: {ReferenceEquals(db1, db2)}"); /* 输出: 数据库连接已创建 执行查询: SELECT * FROM Users db1 和 db2 是同一个实例: True */ } } ``` #### 2. 工厂方法模式 ```csharp public class Shape { // 私有构造函数 private Shape(string type) { Type = type; } public string Type { get; } // 工厂方法 public static Shape CreateCircle() => new Shape("Circle"); public static Shape CreateSquare() => new Shape("Square"); } class Program { static void Main() { var circle = Shape.CreateCircle(); var square = Shape.CreateSquare(); Console.WriteLine($"创建了: {circle.Type}"); // 创建了: Circle Console.WriteLine($"创建了: {square.Type}"); // 创建了: Square // 以下代码会编译错误,因为构造函数是私有的 // var triangle = new Shape("Triangle"); } } ``` #### 3. 工具类(禁止实例化) ```csharp public sealed class MathUtils { // 私有构造函数阻止实例化 private MathUtils() { throw new InvalidOperationException("工具类不应被实例化"); } public static double CalculateCircleArea(double radius) { return Math.PI * radius * radius; } public static double CalculateHypotenuse(double a, double b) { return Math.Sqrt(a * a + b * b); } } class Program { static void Main() { double area = MathUtils.CalculateCircleArea(5); Console.WriteLine($"圆面积: {area}"); // 以下代码会抛出异常 // var utils = new MathUtils(); } } ``` ## 三、静态构造方法私有构造方法的结合使用 ```csharp public class ConfigurationManager { private static readonly ConfigurationManager _instance; private readonly string _configData; // 静态构造函数初始化单例 static ConfigurationManager() { _instance = new ConfigurationManager(); } // 私有构造函数 private ConfigurationManager() { // 模拟加载配置 _configData = "从配置文件加载的配置数据"; Console.WriteLine("配置已加载"); } // 公共访问点 public static ConfigurationManager Instance => _instance; public string GetConfig(string key) { return $"{key}: {_configData}"; } } class Program { static void Main() { // 首次访问时触发静态构造函数 var config = ConfigurationManager.Instance; Console.WriteLine(config.GetConfig("Database")); /* 输出: 配置已加载 Database: 从配置文件加载的配置数据 */ } } ``` ## 四、注意事项和最佳实践 1. **静态构造函数**: - 避免抛出异常(会导致类型在应用程序生命周期内不可用) - 避免执行耗时操作(会阻塞对该类型的首次访问) - 不要依赖调用顺序(不同类的静态构造函数调用顺序不确定) 2. **私有构造函数**: - 考虑将类标记为 `sealed` 防止继承 - 在工具类中,可以在私有构造函数中抛出异常以防止反射创建实例 - 对于单例模式,考虑线程安全实现(如使用 `Lazy<T>`) 3. **线程安全的单例改进**: ```csharp public class ThreadSafeSingleton { private static readonly Lazy<ThreadSafeSingleton> _lazyInstance = new Lazy<ThreadSafeSingleton>(() => new ThreadSafeSingleton()); private ThreadSafeSingleton() { } public static ThreadSafeSingleton Instance => _lazyInstance.Value; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值