为啥这个Java程序中的set 不起作用

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了为啥这个Java程序中的set 不起作用相关的知识,希望对你有一定的参考价值。

首先创建一个Employee类:
import java.util.Date;
import java.util.GregorianCalendar;

class Employee

private String name;
private double salary;
private Date hireDay;

public Employee()



public Employee(String name, double salary, int year, int month, int day)
this.name = name;
this.salary = salary;
GregorianCalendar calendar = new GregorianCalendar(year, month - 1, day);
hireDay = calendar.getTime();


public String getName()
return name;


public double getSalary()
return salary;


public Date getHireDay()
return hireDay;


public void setName(String name)
this.name = name;


public void setSalary(double salary)
this.salary = salary;


public void setHireDay(int year, int month, int day)
GregorianCalendar calendar = new GregorianCalendar(year, month - 1, day);
this.hireDay = calendar.getTime();



public void raiseSalary(double byPercent)
double raise = salary * byPercent / 100;
salary += raise;



然后创建它的测试类:

public class EmployeeTest
public static void main(String[] args)
// fill the staff array with three Employee objects
Employee[] staff = new Employee[4];

staff[0] = new Employee("Carl Cracker", 75000, 1987, 12, 15);
staff[1] = new Employee("Harry Hacker", 50000, 1989, 10, 1);
staff[2] = new Employee("Tony Tester", 40000, 1990, 3, 15);

staff[3].setName("Tom");
staff[3].setSalary(10000);
staff[3].setHireDay(1984, 7, 31);

for (Employee e : staff)
e.raiseSalary(5);

for (Employee e : staff)
System.out.println("name=" + e.getName() + ",salary="
+ e.getSalary() + ",hireDay=" + e.getHireDay());



运行时候报staff[3].setName("Tom");这行空指针异常,请问这是为什么?如何修改

"staff[3].setName("Tom"); "
上面这行代码中,staff[3]这个对象没有初始化。
Employee[] staff = new Employee[4]; 这只是建立了数组的引用,却没有初始化它们。要使用变量,就得先赋值,就像:
staff[2] = new Employee("Tony Tester", 40000, 1990, 3, 15);
上面就是初始化了。
可以这样:
staff[2] = new Employee();
staff[3].setName("Tom");
参考技术A staff[3]根本没有放入对象的引用,也就是说里面根本没有Employee的实例的引用,staff数组本身并没有setName这样的方法,而是Employee的实例才有,你这样调用当然会出错了

为啥 private(set) 在 Swift 中不起作用?

【中文标题】为啥 private(set) 在 Swift 中不起作用?【英文标题】:Why private(set) is not working in Swift?为什么 private(set) 在 Swift 中不起作用? 【发布时间】:2014-08-01 07:55:28 【问题描述】:

来自 Apple 文档:

“上面的每个访问级别修饰符可选地接受一个 参数,由括号中的关键字集组成 (例如,私有(集))。使用这种形式的访问级别 修饰符,当您想为 a 的 setter 指定访问级别时 小于或等于访问级别的变量或下标 变量或下标本身,如 Getters 和 二传手。”

摘自:Apple Inc.“Swift 编程语言”。电子书。 https://itun.es/ru/jEUH0.l

我尝试在 Playground 中测试的示例:

import UIKit


class A 
  private(set) var name: String 
  get  return "Hello, \(self.name)" 
  set  self.name = "Unknown" 
  

  init(_ name:String) 
    self.name = name
  


let a = A("Andrew")
a.name = "Hello"

我在控制台输出中遇到的错误:

Playground execution failed: error: Execution was interrupted, reason: EXC_BAD_ACCESS (code=2, address=0x7fff5056eff8).
The process has been left at the point where it was interrupted, use "thread return -x" to return to the state before expression evaluation.
* thread #1: tid = 0xea721, 0x00000001104f308c libsystem_pthread.dylib`__mtx_droplock + 222, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=2, address=0x7fff5056eff8)
  * frame #0: 0x00000001104f308c libsystem_pthread.dylib`__mtx_droplock + 222
    frame #1: 0x00000001104f2f07 libsystem_pthread.dylib`pthread_mutex_unlock + 68
    frame #2: 0x000000010ffbd2b5 libc++.1.dylib`std::__1::mutex::unlock() + 9
    frame #3: 0x000000010f040b94 libswift_stdlib_core.dylib`swift_getGenericMetadata + 260
    frame #4: 0x000000010ef28a24 libswift_stdlib_core.dylib`Swift.IndexingGenerator.init <A : Swift._Collection>(Swift.IndexingGenerator<A>.Type)(A) -> Swift.IndexingGenerator<A> + 164
    frame #5: 0x000000010ef55f1a libswift_stdlib_core.dylib`protocol witness for Swift._Sequence_.generate <A : Swift._Sequence_>(@inout Swift._Sequence_.Self)() -> Swift._Sequence_.Self.GeneratorType in conformance Swift._ContiguousArrayBuffer : Swift._Sequence_ + 154
    frame #6: 0x000000010ef284d5 libswift_stdlib_core.dylib`Swift._copyCollectionToNativeArrayBuffer <A : protocol<Swift._Collection, Swift._Sequence_>>(A) -> Swift._ContiguousArrayBuffer<A.GeneratorType.Element> + 1061
    frame #7: 0x000000010ef40281 libswift_stdlib_core.dylib`Swift.Array.convertFromArrayLiteral <A>(Swift.Array<A>.Type)(Swift.Array<A>...) -> Swift.Array<A> + 641
    frame #8: 0x000000010f1eaae4 PlaygroundLogger`Swift.UInt64.toBytes (Swift.UInt64)() -> Swift.Array<Swift.UInt8> + 292
    frame #9: 0x000000010f1eb6a4 PlaygroundLogger`protocol witness for PlaygroundLogger.ToBytes.toBytes <A : PlaygroundLogger.ToBytes>(@inout PlaygroundLogger.ToBytes.Self)() -> Swift.Array<Swift.UInt8> in conformance Swift.UInt64 : PlaygroundLogger.ToBytes + 20
    frame #10: 0x000000010f1dbe3d PlaygroundLogger`PlaygroundLogger.BytesStream.write (PlaygroundLogger.BytesStream)(PlaygroundLogger.ToBytes) -> PlaygroundLogger.BytesStream + 77
    frame #11: 0x000000010f1dbd74 PlaygroundLogger`PlaygroundLogger.BytesStream.write (PlaygroundLogger.BytesStream)(Swift.String) -> PlaygroundLogger.BytesStream + 164
    frame #12: 0x000000010f20f04b PlaygroundLogger`PlaygroundLogger.PlaygroundWriter.encode_config_info (PlaygroundLogger.PlaygroundWriter)() -> () + 203
    frame #13: 0x000000010f20f2bf PlaygroundLogger`PlaygroundLogger.PlaygroundWriter.encode_header (PlaygroundLogger.PlaygroundWriter)() -> () + 127
    frame #14: 0x000000010f20ecda PlaygroundLogger`PlaygroundLogger.PlaygroundScopeWriter.encode_scope_event (PlaygroundLogger.PlaygroundScopeWriter)(PlaygroundLogger.ScopeEvent) -> () + 58
    frame #15: 0x000000010f1eb997 PlaygroundLogger`playground_log_scope_entry + 87
    frame #16: 0x000000011ae20771

我做错了什么?我错过了什么吗?

PS1

这个例子运行良好:

struct TrackedString 
  private(set) var numberOfEdits = 0
  var value: String = "" 
  didSet 
    numberOfEdits++
  
  


var stringToEdit = TrackedString()
stringToEdit.value = "Hello"
stringToEdit
stringToEdit.numberOfEdits += 10
stringToEdit

更多来自文档:

“numberOfEdits 属性的访问级别标有 private(set) 修饰符表示该属性应该是可设置的 仅来自与 TrackedString 结构相同的源文件中 定义。”

摘自:Apple Inc.“Swift 编程语言”。电子书。 https://itun.es/ru/jEUH0.l

但这不是我需要的。是否可以禁止在结构/类之外设置变量 numberOfEdits?

【问题讨论】:

您确定是访问控制导致了问题吗?您似乎在自己的设置器中设置变量的值,我认为这会导致无休止的递归。 (你设置名称,调用你的设置器,设置名称,调用你的设置器......) 标题令人困惑。这听起来像一篇文章的标题,它解释了为什么 private(set) 在 Swift 中不起作用。请让我建议将标题更改为“在我的特殊情况下,为什么不能在 Swift 中使用私有(设置)?” 【参考方案1】:

你的问题在这里:

  set  self.name = "Unknown" 

您正在其自己的设置器中设置计算属性的值。这会导致无限递归。不要忘记这是一个 computed 属性:它实际上没有存储空间。您没有变量“self.name”可以放入任何内容;你只有几个函数来计算它。像这样的计算属性应该使用其他非计算变量进行存储。 (顺便说一下,这就是您的结构示例有效的原因:您使用的是具有存储功能的不动产。)

在 Playground 中运行并没有帮助您进行调试。不要误会我的意思:游乐场很棒。但是,在这种情况下,崩溃需要几秒钟的时间,因此崩溃可能不会在您预期的编辑后出现。它也没有向您显示完整的堆栈跟踪(这对于您遇到的问题来说是巨大的,已经在“真实”应用程序中复制了它,并且可能更明显地表明您已经炸毁了堆栈。)当我构建并运行上述作为控制台应用程序,它最终炸毁了堆栈跟踪,深度为 104,832 次调用,其中除了两个之外都是...private_cmd.A.name.setter...。一点线索:)

【讨论】:

以上是关于为啥这个Java程序中的set 不起作用的主要内容,如果未能解决你的问题,请参考以下文章

为啥 set_userdata() 不起作用?

为啥顶部栏中的搜索在 android studio 中不起作用?

为啥我在 paintComponent 中的 gif 动画不起作用?

为啥我在 VB 中的代码不起作用? [关闭]

为啥这个键盘拦截内核扩展不起作用?

Python:为啥这个程序不起作用?