我是Java的新手陷入了一种情况,我的构造函数中有一个excel对象,我必须在我的函数/方法中调用该对象。 我的代码看起来像
public class Hotel {
Hotel() throws BiffException, IOException {
FileInputStream configurationExcel=new FileInputStream("C://Users//Rashmi//Desktop//TravalPS_RegregrestionTest1.xls");
Workbook book = Workbook.getWorkbook(configurationExcel);
Sheet firstsheet= book.getSheet(0);
}
public void test(){
Cell excelcell= firstsheet.getCell(2, 2);//this line is throwing error
}
我想在测试功能中使用第一张对象,我该如何实现呢,
答案 0 :(得分:2)
您希望将firstSheet
分配给该类的成员变量,以便可以通过其他方法访问它:
public class Hotel {
/** Variables defined here are accessible in the entire class */
private Sheet mFirstSheet;
Hotel() throws BiffException, IOException {
/* Variables defined here are only accessible within these curly braces */
FileInputStream configurationExcel = new FileInputStream("...");
Workbook book = Workbook.getWorkbook(configurationExcel);
mFirstSheet = book.getSheet(0);
}
public void test() {
Cell excelcell = mFirstSheet.getCell(2, 2);
}
}
请注意定义和初始化之间的区别。 mFirstSheet
在类的主体中(在类的花括号内)定义,但在构造函数中初始化。它是定义变量的地方,用于确定可从中访问的位置。
关于辅助功能的另一点,您的类被定义为 public ,但您的构造函数(Hotel() ...
)上没有修饰符。在Java中,这默认为包私有(意味着只有同一个包中的其他类,或者如果没有包,则相同的目录,请参阅此构造函数)。这意味着虽然其他包中的类看到了类,但它们无法创建它的新版本。这可能是你的意图,并且有一些用途,但我猜它不是,所以你可能也想让你的构造函数公开:public Hotel() ...
有了这个关于范围界定的新知识,可能很容易做到这一点,以便所有地方都可以访问,#justincase。不要这样做。原因如下:
它污染名称空间
假设您有多种方法从工作表中获取单元格,但您已将excelcell
变量定义为类中的私有字段(与mFirstSheet
位于同一位置)。现在,所有与先前完全不同的单元格交互的方法都将它们存储在同一个变量中。现在这对你来说是一个额外的麻烦,确保方法在使用之前正确初始化excelcell
,否则它将获得一些其他方法的单元格,因此这个变量应保持作用于它所使用的每个方法。< / p>
它留下了很长的生活参考资料
Java 垃圾收集,这意味着,当内存不足时,会有一个名为垃圾收集器的系统,它会查找不再附加任何引用的对象对他们而言,释放与他们相关的记忆。一旦你离开了方法的范围,那里定义的变量就不再可以访问了,所以如果不存在对它们的其他引用,垃圾收集器就可以去掉它们。但是,如果您将所有变量分配为该类的私有字段,那么只要该类的实例存在,它们就会存在至少(因为该实例现在包含对该对象的引用)。
这个对象的一个很好的例子就是你的configurationExcel
变量。就目前而言,一旦离开构造函数,它很可能是垃圾收集。哪个好,因为它包含一个文件指针,你真的不希望保持打开时间超过必要的时间(book
可能有一个引用它,但我猜它是因为它的目的是它可能不会)。但是,如果它是一个私有字段,它就会像类的实例一样长,一直没用,它的内存浪费了。
打破封装
除非公开私有字段,否则并非总是如此。您会注意到,当我定义mFirstSheet
时,我将其设为private Sheet
。这意味着它只能由此类本身(及其内部类和静态上下文)访问。如果你要将它定义为public Sheet mFirstSheet
,那么任何东西都可以访问,这可能看起来是一个好主意,因为它可以节省你必须编写一个getter来让你的程序的其他部分访问它,,但这不是一个好主意。这意味着您无法控制类的内部状态会发生什么,任何事情都可以取代它:
public class ChaosMonkey() {
public static void wreakHavoc(Hotel hotel) {
hotel.mFirstSheet = null;
/** Havoc wreaked */
}
}
你不知道何时,为何或如何。
(您可能正在思考:如果我做希望其他类能够修改mFirstSheet
该怎么办。如果它是您的类的设计的一部分,那么其他类应该能够在没有任何限制的情况下改变其内部状态,那么这是一个糟糕的设计,并且表明该字段不属于该类的事实。)
答案 1 :(得分:1)
firstsheet
不是字段,而是构造函数中的局部变量,因此您无法通过test()
方法访问它。
public class Hotel {
private FileInputStream configurationExcel;
private Sheet firstsheet;
private Workbook book;
public Hotel() throws BiffException, IOException {
this.configurationExcel=new FileInputStream("C://Users//Rashmi//Desktop//TravalPS_RegregrestionTest1.xls");
this.book = Workbook.getWorkbook(configurationExcel);
this.firstsheet= book.getSheet(0);
}
public void test(){
Cell excelcell= this.firstsheet.getCell(2, 2);//this line is throwing error
}
答案 2 :(得分:1)
好。有两种类型的变量。 成员变量和局部变量。
成员变量是类的一部分,并为类声明。 像这样的东西
public class Hotel {
**private String hotelName;**
protected void bookHotel(){
this.hotelName = "Something";
.....
}
}
在成员变量中,您可以看到类方法中的变量。
在函数中初始化或使用局部变量。其中一个例子就是您在 For 循环中使用的变量。
public class Hotel {
**private String hotelName;**
protected void bookHotel(){
**String myHotelName = "Marriott";**
this.hotelName = myHotelName;
.....
}
}
这里myHotelName是一个局部变量,不能在另一种方法中访问。
现在,在您的情况下,firstSheet不是成员变量,而是局部变量。因此,它不能用另一种方法访问。要使用它,如果你确实需要使用它,它必须是该类的成员变量。
答案 3 :(得分:1)
对象firstsheet只存在于构造函数的范围内。如果要在其他方法中使用它,则必须将其声明为全局字段。这是一个例子:
public class Hotel {
private Sheet firstsheet; // firstsheet is a global field
// Constructor
public Hotel() throws BiffException, IOException {
FileInputStream configurationExcel=new FileInputStream("C://Users//Rashmi//Desktop//TravalPS_RegregrestionTest1.xls");
Workbook book = Workbook.getWorkbook(configurationExcel);
firstsheet= book.getSheet(0); // firstsheet get's a value
}
// Some method
public void test(){
Cell excelcell = firstsheet.getCell(2, 2); // firstsheet also exists in this scope now
}
}