为什么在外部 class 的 <> 括号内写一个内部私有 class 会出错?

Why writing an Inner Private class inside <> bracket of outer class makes error?

我正在尝试将私有 class 插入到外部 class 声明的括号(泛型)中并出现下一个错误:“com.example.gridrecyclerview.RecyclerViewAdapter.VieHolder 在 [=20 中具有私有访问权限=]"

将内部 class 更改为 public 一切正常。有人可以向我解释这个问题。 附代码:

    package com.example.gridrecyclerview;

import android.content.Context;
import android.graphics.Color;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;

import java.util.List;
import java.util.Random;

public class RecyclerViewAdapter extends RecyclerView.Adapter <RecyclerViewAdapter.ViewHolder> {
    Context context;
    List<ModelItem> modelItemList;

    public RecyclerViewAdapter(Context context, List<ModelItem> modelItemList)
    {
        this.context = context;
        this.modelItemList = modelItemList;
    }

    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType)
    {
        View view = LayoutInflater.from(context).inflate(R.layout.rc_item,parent,false);
        return new ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, int position)
    {
        Log.e("onBindViewHolder ","onBindViewHolder");
        ModelItem modelItem = modelItemList.get(position);
        holder.firstNameTextView.setText(modelItem.getFirstName());
        holder.secondNameText.setText(modelItem.getLastName());
    }

    @Override
    public int getItemCount()
    {
        return modelItemList.size();
    }

    private class ViewHolder extends RecyclerView.ViewHolder
    {

        TextView firstNameTextView;
        TextView secondNameText;
        public ViewHolder(@NonNull View itemView)
        {
            super(itemView);
            firstNameTextView = itemView.findViewById(R.id.first_name);
            secondNameText = itemView.findViewById(R.id.second_name);
        }
    }
}

你不能这样做,因为你正在将私有 class 传递给“RecyclerView.Adapter”class。换句话说,ViewHolder class 仅在 RecyclerViewAdapter class.

内部可用

PS:您可以将此 class 创建为新的 Class,然后将其传递给“RecyclerView.Adapter” class 或将其更改为 public范围。

要回答这个问题你应该知道当你在Java中使用泛型时幕后发生了什么,泛型在编译时被检查并且在运行时没有泛型类型这被称为类型擦除,当你编译你的程序,所有泛型都是特定类型的种姓。想象一下你的 RecyclerView.Adapter class 是这样的:

public class Adapter<T> {
    T view;

    public T getView() {
        return view;
    }

    public void setView(T view) {
        this.view = view;
    }
}

假设您已经像以前一样定义了 RecyclerViewAdapter class:

现在让我们从两个角度讨论这个问题:

  1. 程序员
  2. 编译器

作为程序员想象在另一个 class 中的某处,您创建 RecyclerViewAdapter class 的实例如下并在该对象上调用 getView():

RecyclerViewAdapter recycler = RecyclerViewAdapter();
? object =  recycler.getView()

你放在这里的是什么类型的对象? 显然你不能放 RecyclerViewAdapter.ViewHolder 因为它对 RecyclerViewAdapter 是私有的,你不能在其他地方使用它。

现在让我们从编译器的角度考虑这个问题:

编译泛型时,编译器使用擦除并将您的代码编译成这样:

RecyclerViewAdapter recycler = RecyclerViewAdapter();
? object =  (RecyclerViewAdapter.ViewHolder)recycler.getView();

在这里你可以看到编译器在编译时转换你的对象的类型((RecyclerViewAdapter.ViewHolder)recycler.getView())。但是编译器有可能在这里做这样的事情吗?

当然不是因为 RecyclerViewAdapter.ViewHolderRecyclerViewAdapter class 是私有的,而这段代码是在另一个 class.

中编写的

根据Java-Spec页-164中的可访问性规则,声明的私有成员只能在顶级class的主体内访问。我希望 class 的主体不是它的定义。

** 否则,成员或构造函数被声明为私有,当且仅当它发生在包含成员或构造函数声明的顶层 class (§7.6) 的主体内时才允许访问. **