为什么在外部类的 <> 括号内编写内部私有类会出错?

huangapple go评论75阅读模式
英文:

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

问题

我试图将一个私有类插入外部类声明的尖括号(泛型)中,但是得到了以下错误:“com.example.gridrecyclerview.RecyclerViewAdapter.VieHolder 在 com.example.gridrecyclerview.RecyclerViewAdapter 中具有私有访问权限”

当将内部类更改为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);
        }
    }
}
英文:

I'm trying to insert a private class into brackets (Generics) of outer class declaration and getting the next error : "com.example.gridrecyclerview.RecyclerViewAdapter.VieHolder has private access in com.example.gridrecyclerview.RecyclerViewAdapter"

When changing inner class to public everything ok. Can someone explain me the issue.
Attached code:

    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 &lt;RecyclerViewAdapter.ViewHolder&gt; {
Context context;
List&lt;ModelItem&gt; modelItemList;
public RecyclerViewAdapter(Context context, List&lt;ModelItem&gt; 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(&quot;onBindViewHolder &quot;,&quot;onBindViewHolder&quot;);
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);
}
}
}

答案1

得分: 0

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

附注:你可以将这个类创建为一个新类,然后通过“RecyclerView.Adapter”类传递它,或者将其改为公共作用域。

英文:

You can not do this, because there you are passing the private class to "RecyclerView.Adapter" class. In other words, the ViewHolder class only available inside the RecyclerViewAdapter class.

PS: You can create this class as a new Class, then pass it through "RecyclerView.Adapter" class or change it to public scope.

答案2

得分: 0

要回答这个问题,您应该知道在使用Java中的泛型时发生了什么,泛型在编译时进行检查,但在运行时没有泛型类型,这被称为类型擦除,当您编译程序时,所有的泛型都被转换为它们特定的类型。想象一下您的RecyclerView.Adapter类如下所示:

public class Adapter<T> {
    T view;

    public T getView() {
        return view;
    }

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

并且想象一下您之前定义的RecyclerViewAdapter类:

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

  1. 程序员
  2. 编译器

作为一个程序员,想象一下在另一个类中的某个地方,您创建了一个RecyclerViewAdapter类的实例,并在该对象上调用getView()

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

在这里,您应该用什么样的对象来代替?显然,您不能使用RecyclerViewAdapter.ViewHolder,因为它对于RecyclerViewAdapter来说是私有的,您无法在其他地方使用它。

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

在编译泛型时,编译器使用擦除将您的代码编译为类似于这样的内容:

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

在这里,您可以看到编译器在编译时将对象的类型转换为特定类型((RecyclerViewAdapter.ViewHolder) recycler.getView())。但编译器是否可以在这里执行类似的操作呢?

当然不行,因为RecyclerViewAdapter.ViewHolder对于RecyclerViewAdapter类来说是私有的,而这段代码是在另一个类中编写的。

英文:

To answer this question you should know what happened behind the scene when you use generics in Java, Generics are checked at compile time and there is no generic type at runtime this is called type erasure, when you compile your program all generics are castes to their specific types. Imagine your RecyclerView.Adapter class is something as follow:

public class Adapter&lt;T&gt; {
T view;
public T getView() {
return view;
}
public void setView(T view) {
this.view = view;
}
}

And Imagine you have defined your RecyclerViewAdapter class as before:

Now lets discuss this problem from two points of view:

  1. Programmer
  2. Compiler

As a programmer imagine somewhere in another class you create an instance of RecyclerViewAdapter class as follow and call getView() on that object:

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

What type of object you put here instead of ?
clearly you can't put RecyclerViewAdapter.ViewHolder because it is private for RecyclerViewAdapter and you can't use it elsewhere.

Now lets consider this problem from compiler point of view:

When compiling generics, compiler use erasure and compile your code to something like this:

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

Here you can see compiler cast the type of your object at compile time((RecyclerViewAdapter.ViewHolder)recycler.getView()). But is it possible for compiler to do something like this here?

Of course not because RecyclerViewAdapter.ViewHolder is private for RecyclerViewAdapter class while this code is written in another class.

答案3

得分: 0

根据Java规范第164页中的可访问性规则,声明为private的成员只能在顶级类的主体内访问。我希望“类的主体”指的不是其定义。

否则,如果成员或构造函数被声明为private,只有在它出现在封闭成员或构造函数声明的顶级类(§7.6)的主体内时,才允许访问。

英文:

As per the accessibility rule in Java-Spec Page -164, a private member declared is accessible only within the body of the top level class. I hope body of the class means not the definition of it.

**
Otherwise, the member or constructor is declared private, and access is permitted if and only if it occurs within the body of the top level class (§7.6) that encloses the declaration of the member or constructor.
**

huangapple
  • 本文由 发表于 2020年7月25日 03:03:44
  • 转载请务必保留本文链接:https://go.coder-hub.com/63079980.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定