是否可以直接从main修改类的私有成员?

时间:2013-08-09 09:30:42

标签: java

我已经创建了一个堆栈的私有类成员,并且不知道如何直接或间接地从main方法访问它,尽管我没有使用任何对象。当程序执行排序方法时,它会自动直接修改私有成员“stk []”。

当从main方法调用排序选项时,这是从main方法间接修改私有String stk []的代码:

import java.io.*;
class Stack
{
   private String stk[];
   private int tos;
   private int size;
   Stack()
   {
      size=5;
      stk=new String[size];
      tos=-1;
   }
   Stack(int sz)
   {
      size=sz;
      stk=new String[size];
      tos=-1;
   }
   boolean push(String s)
   {
      if(tos==size-1) return false;
      stk[++tos]=s;
      return true;
   }
   String pop()
   {
      if(tos<0) return "Stack Underflow";
      return stk[tos--];
   }
   String[] display()//array type function to return an array called "stk"
   {
      return stk;
   }
   int returnSize()
   {
      return tos;
   }
}
class myStack
{
   public static void main(String args[]) throws IOException
   {
      BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
      Stack S=new Stack();
      int opt=-1;
      while(opt!=6)
      {
         System.out.println("\n\n\n");
         System.out.println("[1] - Create Stack");
         System.out.println("[2] - Push");
         System.out.println("[3] - Pop");
         System.out.println("[4] - Display");
         System.out.println("[5] - Display List In Ascending Order");
         System.out.println("[6] - Exit");
         System.out.print("Option: ");
         opt=Integer.parseInt(br.readLine());
         if(opt==1)
         {
            System.out.print("\n\nEnter the size of stack: ");
            int size=Integer.parseInt(br.readLine());
            S=new Stack(size);
            System.out.print("\nStack Created...");
         }
         else if(opt==2)
         {
            System.out.print("\n\nEnter String: ");
            String s=br.readLine();
            if(S.push(s))
               System.out.print("\nSuccessfull...");
            else
               System.out.print("\nStack Overflow...");
         }
         else if(opt==3)
         {
            System.out.print("\nItem Deleted: "+S.pop());
         }
         else if(opt==4)
         {
            int sz=S.returnSize();
            System.out.print("\n\n\nStack Contains: "+(sz+1)+" Item(s)\n");
            String st[]=S.display();
            while(sz>=0)
            {
               System.out.println(st[sz]);
               sz--;
            }
         }
         else if(opt==5)
         {
            int s=S.returnSize();
            String stc[]=S.display();
            for(int i=0;i<=s;i++)
            {
               for(int j=i+1;j<=s;j++)
               {
                  if(stc[j].compareTo(stc[i])<0)
                  {
                     String t=stc[i];
                     stc[i]=stc[j];
                     stc[j]=t;
                  }
               }
               System.out.println(stc[i]);
            }
         }
         else if(opt>6)
         {
            System.out.print("\nPress 6 To Exit....");
         }
      }
   }
}

4 个答案:

答案 0 :(得分:1)

我认为这就是你所关注的......

String stc[]=S.display();
       for(int i=0;i<=s;i++) {
         for(int j=i+1;j<=s;j++) {
             if(stc[j].compareTo(stc[i])<0) {
                  String t=stc[i];
                  stc[i]=stc[j];
                  stc[j]=t;
             }
         }
         System.out.println(stc[i]);
        }

当您致电S.display时,您将传递对数组的引用,并将该引用存储在stc中。然后会修改stc,但由于stc --> array <--- stk,您将同时编辑它们。

答案 1 :(得分:0)

私人意味着即使在主要课程中你也无法在课堂外访问它,我认为如果你的成员是私人的并且你想要在外面访问它们,那么这不是很好的实践,那么如果你想私下访问它们,你为什么要在外面访问它们。公开见下文。

public class Stack
{
}

答案 2 :(得分:0)

私人就是这个意思。该值在其所属的类之外是不可见的。

你可以用反射来改变它,但你不应该。如果它是你的类成员所属,那么编写一个公共方法来获取/更改变量。如果它不是您的类,那么该值不会直接显示/更改。改变这种情况(带有重新选择)会带来危险。

答案 3 :(得分:0)

在这种情况下,重要的是要区分immutable and mutable objects

创建对象后无法更改

例如:

String s = “foo”;

无法更改变量s引用的String对象。该对象将始终包含数据“foo”。如果执行s.concat(“bar);,则s引用的String对象不会更改。相反,方法调用将返回一个全新的String对象,它是“foo”和“bar”的串联。

可变对象可以更改

例如:

List<Integer> l = new List<Integer>();

以上是一个空列表对象。但是,如果我们调用l.add(42);,我们实际上已经更改了变量l引用的List对象。

为什么这种区别很重要?

如果要在类中封装实现细节,则不能通过类的公共接口返回任何引用可变对象的私有实例变量。

这就是发生的事情。您将返回对私有stk数组的引用。但是数组是可变的,因此返回的引用可用于修改引用的数组对象。

如何防止这种情况?

一种方法是使用defensive copying。这意味着您应该返回可变对象的副本,而不是可变对象本身。 例如:

String[] display() {
    Arrays.copyOf(stk, stk.length);
}

这样,在使用返回引用的客户端代码中执行的任何更改都只会影响复制的对象,并且您的私有数组对象将保持不变。