使用另一个类的私有类构造函数访问内部子类

Posted

技术标签:

【中文标题】使用另一个类的私有类构造函数访问内部子类【英文标题】:Accessing an inner subclass with private class constructor from another class 【发布时间】:2018-02-19 14:56:04 【问题描述】:

我正在创建 SQL 数据库,我基于 this site. 问题是,我不知道如何访问内部类的方法,而外部类有私有构造函数。

public class MyDBHandler 

    private MyDBHandler() 
    

    public static class FeedEntry implements BaseColumns 
        public static final String TABLE_NAME = "Tasks";
        public static final String COLUMN_NAME_TITLE = "TASK_LABEL";
    

    public class FeedReaderDbHelper extends SQLiteOpenHelper 
        public static final int DATABASE_VERSION = 1;
        public static final String DATABASE_NAME = "myDatabase.db";

        public FeedReaderDbHelper(Context context) 
            super(context, DATABASE_NAME, null, DATABASE_VERSION);
        

        public long saveTasks(String title) 
            SQLiteDatabase db = this.getWritableDatabase();

            ContentValues contentValues = new ContentValues();
            contentValues.put(FeedEntry.COLUMN_NAME_TITLE, title);

            long newRowId = db.insert(FeedEntry.TABLE_NAME, null, contentValues);
            return newRowId;

        
    
 

我正在尝试从另一个 java 文件的 onClick(View v) 方法访问 saveTasks(String title) 方法。

我试过这样的:

MyDBHandler.FeedReaderDbHelper dbHelper = new MyDBHandler.FeedReaderDbHelper(v.getContext());

但我当然会收到“MyDBHandler 不是封闭类”错误。

MyDBHandler.FeedReaderDbHelper dbHelper= new MyDBHandler().new FeedReaderDbHelper(v.getContext());

android 工作室再次告诉我:“MyDbHandler 具有私有访问权限”

这种方式有可能吗?

【问题讨论】:

将 FeedReaderDbHelper 类移动到单独的文件中 你为什么将它作为一个内部类来实现?在示例中,它显然是一个单独的类。 为什么不能公开构造函数? 【参考方案1】:

内部类只是将一些真正属于原始外部类的功能干净地分开的一种方式。当您有 2 个要求时使用它们:

    外部类中的某些功能将是最清楚的 如果它是在一个单独的类中实现的。 即使它在一个单独的类中,其功能也非常紧密地联系在一起 外部类的工作方式。

鉴于这些要求,内部类可以完全访问其外部类。由于它们基本上是外部类的成员,因此它们可以访问外部类的方法和属性是有道理的——包括私有

以下是方法:

new MyDBHandler.FeedReaderDbHelper(getContext())  

I have run your code by following way, Please have a look.

public class MyDBHandler 

        public static FeedReaderDbHelper feedReaderDbHelper;
        private MyDBHandler() 
        

        public static FeedReaderDbHelper getFeedReaderDbHelper()
        
            if(feedReaderDbHelper == null)
                feedReaderDbHelper = new MyDBHandler(). new FeedReaderDbHelper();

            return feedReaderDbHelper;
        
        public static class FeedEntry  
            public static final String TABLE_NAME = "Tasks";
            public static final String COLUMN_NAME_TITLE = "TASK_LABEL";
        

        public class FeedReaderDbHelper  
            public static final int DATABASE_VERSION = 1;
            public static final String DATABASE_NAME = "myDatabase.db";

            public FeedReaderDbHelper() 
                //super(context, DATABASE_NAME, null, DATABASE_VERSION);
            

            public long saveTasks(String title) 
                System.out.println(title);

                return 1L;
            
        


        public static void main(String[] args) 
            MyDBHandler.getFeedReaderDbHelper().saveTasks("title");
        
    

【讨论】:

【参考方案2】:

你可以让内部类静态来使用它

public class MyDBHandler 

private MyDBHandler() 


public static class FeedEntry implements BaseColumns 
    public static final String TABLE_NAME = "Tasks";
    public static final String COLUMN_NAME_TITLE = "TASK_LABEL";


public static class FeedReaderDbHelper extends SQLiteOpenHelper 
    public static final int DATABASE_VERSION = 1;
    public static final String DATABASE_NAME = "myDatabase.db";

    public FeedReaderDbHelper(Context context) 
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
    

    public long saveTasks(String title) 
        SQLiteDatabase db = this.getWritableDatabase();

        ContentValues contentValues = new ContentValues();
        contentValues.put(FeedEntry.COLUMN_NAME_TITLE, title);

        long newRowId = db.insert(FeedEntry.TABLE_NAME, null, contentValues);
        return newRowId;

    
  
 

现在要获取 FeedReaderDbHelper 的实例,您可以

MyDBHandler.FeedReaderDbHelper dbHelper = new MyDBHandler.FeedReaderDbHelper(v.getContext());

调用方法

String title = "your title";
dbHelper.saveTasks(title)

【讨论】:

【参考方案3】:
MyDbHandler has a private access

这不是关于内部类,而是关于该类中的构造函数

private MyDBHandler() 

我想我之前看过这个指南(网站),我真的不知道他们为什么将它添加为内部类。我记得他们说过要将构造函数设为私有,因此没有人可以从中创建对象。 所以只需将FeedReaderDbHelper 移动到一个单独的文件中即可。

但是如果出于某种原因你想保留它的内部类,那么将它定义为静态

public static class FeedReaderDbHelper

然后调用相同的代码,它应该可以工作

【讨论】:

问题是,当我将 FeedReaderDbHelper 移动到单独的文件时,它只是无法访问变量,例如 SQL_DELETE_ENTRIES。我必须创建吸气剂来解决它。这会是最佳解决方案吗? 当然它可以访问它们是 decalered public static 所以你可以像这样访问它们 CLASS_NAME.STATIC_PUBLIC_VARS,否则只有 getters 才是最佳选择是的 是的,我只是想尽可能多地坚持这个 android 开发指南,其中 vars 是私有的。无论如何,我只会使用 getter。【参考方案4】:

如果你真的想保留你的内部类,那么让它静态并按如下方式使用它:

new MyDBHandler.FeedReaderDbHelper(getContext())

【讨论】:

以上是关于使用另一个类的私有类构造函数访问内部子类的主要内容,如果未能解决你的问题,请参考以下文章

抽象类中的私有构造函数

如何访问类的私有构造函数?

类的继承

为啥Java反射在另一个包中找不到一个类的包私有构造函数?

子类从父类继承过来的方法可以操作子类自己定义的成员变量吗

JavaSE复习_3 继承