29
loading...
This website collects cookies to deliver better user experience
public class DeviceController {
…
public void sendShutDown() {
DeviceHandle handle = getHandle(DEV1);
// Check the state of the device
if (handle != DeviceHandle.INVALID) {
// Save the device status to the record field
retrieveDeviceRecord(handle);
// If not suspended, shut down
if (record.getStatus() != DEVICE_SUSPENDED) {
pauseDevice(handle);
clearDeviceWorkQueue(handle);
closeDevice(handle);
} else {
logger.log("Device suspended. Unable to shut down");
}
} else {
logger.log("Invalid handle for: " + DEV1.toString());
}
}
...
}
public class DeviceController {
…
public void sendShutDown() {
try {
tryToShutDown();
} catch (DeviceShutDownError e) {
logger.log(e);
}
}
private void tryToShutDown() throws DeviceShutDownError {
DeviceHandle handle = getHandle(DEV1);
DeviceRecord record = retrieveDeviceRecord(handle);
pauseDevice(handle);
clearDeviceWorkQueue(handle);
closeDevice(handle);
}
private DeviceHandle getHandle(DeviceID id) {
…
throw new DeviceShutDownError("Invalid handle for: " + id.toString());
…
}
...
}
try
, você declara que aquela execução pode ser cancelada a qualquer momento e então continuar no catch.try
são como transações. Seu catch
tem que deixar seu programa num estado consistente, não importa o que aconteça no try
.try...catch...finally
quando for escrever um código que talvez lance exceções. Isso ajuda a definir o que o usuário do código deve esperar, independente do que ocorra de errado no código que é executado no try
.@Test(expected = StorageException.class)
public void retrieveSectionShouldThrowOnInvalidFileName() {
sectionStore.retrieveSection("invalid - file");
}
public List<RecordedGrip> retrieveSection(String sectionName) {
// dummy return until we have a real implementation
return new ArrayList<RecordedGrip>();
}
public List<RecordedGrip> retrieveSection(String sectionName) {
try {
FileInputStream stream = new FileInputStream(sectionName);
} catch (Exception e) {
throw new StorageException("retrieval error", e);
}
return new ArrayList<RecordedGrip>();
}
FileInputStream
:
public List<RecordedGrip> retrieveSection(String sectionName) {
try {
FileInputStream stream = new FileInputStream(sectionName);
stream.close();
} catch (FileNotFoundException e) {
throw new StorageException("retrieval error”, e);
}
return new ArrayList<RecordedGrip>();
}
stack trace
de qualquer exceção. Porém ela não consegue dizer o motivo da falha da operação.ACMEPort port = new ACMEPort(12);
try {
port.open();
} catch (DeviceResponseException e) {
reportPortError(e);
logger.log("Device response exception", e);
} catch (ATM1212UnlockedException e) {
reportPortError(e);
logger.log("Unlock exception", e);
} catch (GMXError e) {
reportPortError(e);
logger.log("Device response exception");
} finally {
…
}
LocalPort port = new LocalPort(12);
try {
port.open();
} catch (PortDeviceFailure e) {
reportError(e);
logger.log(e.getMessage(), e);
} finally {
…
}
LocalPort
é um simples wrapper (empacotador) que captura e traduz as exceções:
public class LocalPort {
private ACMEPort innerPort;
public LocalPort(int portNumber) {
innerPort = new ACMEPort(portNumber);
}
public void open() {
try {
innerPort.open();
} catch (DeviceResponseException e) {
throw new PortDeviceFailure(e);
} catch (ATM1212UnlockedException e) {
throw new PortDeviceFailure(e);
} catch (GMXError e) {
throw new PortDeviceFailure(e);
}
}
…
}
try {
MealExpenses expenses = expenseReportDAO.getMeals(employee.getID());
m_total += expenses.getTotal();
} catch(MealExpensesNotFound e) {
m_total += getMealPerDiem();
}
MealExpenses expenses = expenseReportDAO.getMeals(employee.getID());
m_total += expenses.getTotal();
ExpenseReportDAO
para que ele sempre retorne um objeto MealExpenses
. Se não houver gastos com refeições, ele retorna um objeto PerDiemMealExpenses
que retorna a diária como seu total:
public class PerDiemMealExpenses implements MealExpenses {
public int getTotal() {
// retorna a ajuda de custo padrão
}
}
public void registerItem(Item item) {
if (item != null) {
ItemRegistry registry = peristentStore.getItemRegistry();
if (registry != null) {
Item existing = registry.getItem(item.getID());
if (existing.getBillingPeriod().hasRetailOwner()) {
existing.register(item);
}
}
}
}
null
, estamos criando mais trabalho para nós mesmos e jogando problemas em cima de nossos chamadores. Só basta esquecer uma verificação null
para que o aplicativo fique fora de controle.null
na segunda linha do if
aninhado? E se peristentStore
fosse null
?null
. null
de um método, lance uma exceção ou um objeto SPECIAL CASE!null
use o empacotamento ou o objeto de caso especial.List<Employee> employees = getEmployees();
if (employees != null) {
for(Employee e : employees) {
totalPay += e.getPay();
}
}
null
:
List<Employee> employees = getEmployees();
for(Employee e : employees) {
totalPay += e.getPay();
}
getEmployees
:public List<Employee> getEmployees() {
if( .. there are no employees .. )
return Collections.emptyList();
}
NullPointerException
e o código será mais limpo.null
dos métodos é ruim, mas passar null
para eles é pior ainda.null
, devemos evitar passá-lo.public class MetricsCalculator {
public double xProjection(Point p1, Point p2) {
return (p2.x – p1.x) * 1.5;
}
…
}
null
para o método acima receberemos uma NullPointerException
!public class MetricsCalculator {
public double xProjection(Point p1, Point p2) {
if (p1 == null || p2 == null) {
throw InvalidArgumentException("Invalid argument for MetricsCalculator.xProjection");
}
return (p2.x – p1.x) * 1.5;
}
}
null
é sinal de problema e pode gerar mais erros por descuido.29