-2

我已经创建了堆栈的私有类成员,但不知道如何从主方法直接或间接访问它,尽管我没有使用任何对象。程序执行排序方法时,直接自动修改私有成员“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

4 回答 4

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. stcthen 已修改,但因为stc --> array <--- stk,您将同时编辑两者。

于 2013-08-09T09:35:46.477 回答
0

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

你可以用反射来改变它,但你不应该。如果它是您的成员所属的类,则编写一个公共方法来获取/更改变量。如果它不是您的类,则该值不打算直接可见/更改。更改此(重新选择)后果自负。

于 2013-08-09T09:37:26.557 回答
0

Private means you can't access it outside the class even in main and i think it is not good pratice if your member are private and you want to access them outside then why you want to access them outside if they are private. make it public see below.

public class Stack
{
}
于 2013-08-09T09:35:55.720 回答
0

在这种情况下,重要的是要区分不可变对象和可变对象

不可变对象在创建后无法更改

例如:

String s = “foo”;

变量引用的 String 对象是不可能改变的s。该对象将始终包含数据“foo”。如果这样做s.concat(“bar);,则引用的 String 对象s不会改变。相反,方法调用将返回一个全新的 String 对象,它是“foo”和“bar”的连接。

可变对象可以改变

例如:

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

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

为什么这种区别很重要?

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

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

如何防止这种情况?

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

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

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

于 2013-08-09T10:35:15.277 回答