Skip to main content

Java Keywords (Part XXIV): native

Java keyword list abstract continue for new switch assert default goto * package synchronized boolean do if private this break double implements protected throw byte else import public throws case enum instanceof return transient catch extends int short try char final interface static void class finally long strictfp volatile const * float native super while Keyword marked with an asterisk (*) are keywords that, although valid, are not used by programmers. This is the last chapter of the Java Keyword series. This is probably the keyword I have used the least. In my 20 year career as a software developer, I have used this keyword once, and that was to make some addition to legacy code. The keyword native is a method modifier . Basically, it is a keyword that can only be applied to methods. According to the Java Language Specification (JLS), A method that is native is implemented i...

Creating Custom Exception Classes in Java


Introduction

My first piece of advice: Search the web. There is a ton of information that is available to you on the Internet. However, beware where you go for information. There are many places with bad information as well. For this topic, the safest source of information is the Oracle The Java Exceptions Tutorials.

Starting with the basics, the first thing to do is determine whether or not you need the custom exception class to begin with. We are going to assume we need to handle an exception that it is not clearly represented already in Java.

To create a custom exception class, we must use a name that it is meaningful. Typically, the exception class is named after a process or a class name that will throw the exception. For instance, if I create a MessageReceiver class that could result in an exception, I might consider naming my exception class MessageReceiverException. The UML diagram below depicts this relationship between the class and the custom exception class:


Notice that there is only an association relationship between MessageReceiver and MessageReceiverException. That means that MessageReceiver “uses” MessageReceiverException.

Choosing a Name for the Class

In my example, I chose for my custom exception class to extend Exception. This does not have to be the case all the time. Any Exception subclass can be used as the parent class of MessageReceiverException. However, a quick perusal of those subclasses shows that they are inappropriate because they are either too specialized or completely unrelated to MessageReceiverException. Therefore, the parent class of MessageReceiverException should be Exception.

Exception Class Contents: Constructors

Your class should contain 4 constructors. Following the UML diagram above, my MessageReceiverException class should look as follows:


public class MessageReceiverException extends Exception
{
 private String message;

 public MessageReceiverException()
 {
  super();
  message = "MessageReceiver class encountered an unknown condition.";
 }
 
 public MessageReceiverException(String message)
 {
  super(message);
  this.message = message;
 }
 
 public MessageReceiverException(String message, Throwable cause)
 {
  super(message, cause);
  this.message = message;
 }
 
 public MessageReceiverException(Throwable cause)
 {
  super(cause);
  message = (cause == null ? null : cause.toString());
 }
}


Examining the code, you can see how the no-argument constructor could be used for a default case where a default message is constructed. In the next two cases, a message is constructed by the user (client) of the class; in this example, MessageReceiver. Because the MessageReceiver has two methods, it is possible that both could result in an exception being thrown. However, the message generated for exception occurring inside the onMessage method might (and most likely will) be different than the message generated inside the processMessage method. The last case examines the cause (Throwable) object and obtains the message set in it if the object is not null.

Getting the Message

The Throwable class (the immediate parent of Exception) implemented many methods that the Exception class inherited and uses as-is (no method overriding). Because of this fact, it should not be necessary to override these methods. Amongst the most used methods are: getLocalizedMessage, getMessage, printStackTrace, and toString.

The Client Class

Creating a custom exception class is meaningless unless there is another class who will throw that type of exception when something goes wrong. Therefore, the client class’ affected methods must indicate the kind of exceptions they throw (if any). In this example, the class has two methods that could result in the same exception TYPE (not the same exception) being thrown. However, this does not have to be the case all the time. Additionally, a method could throw more than one type of exception. On such cases, the exceptions must be listed separated by comma (i.e. throws IOException, FileNotFoundException, etc.)


public interface IMessageReceiver
{
 public void onMessage(Message message) throws MessageReceiverException;
}
public class MessageReceiver implements IMessageReceiver
{
 @Override
 public void onMessage(Message message) throws MessageReceiverException
 {
  if(message != null)
  {
   processMessage(message);
  }
  else
  {
   throw new MessageReceiverException("The message object was null.");
  }
 }
 
 private void processMessage(Message message) throws MessageReceiverException
 {
  if(message.getContents() != null && !message.getContents().isEmpty())
  {
   //TODO: Process the contents of the message and do something with it
  }
  else
  {
   throw new MessageReceiverException("The message contains no information.");
  }
 }
}



public class Message
{
 private String to;
 private String from = "";
 private String subject = "";
 private String contents;
 
 public Message(String to, String contents)
 {
  this.to= to;
  this.contents = contents;
 }

 public String getTo()
 {
  return to;
 }
 public String getFrom()
 {
  return from;
 }
 public String getSubject()
 {
  return subject;
 }
 public String getContents()
 {
  return contents;
 }
 public void setFrom(String from)
 {
  this.from = from;
 }
 public void setSubject(String subject)
 {
  this.subject = subject;
 }
 
 @Override
 public String toString()
 {
  StringBuilder strBldr = new StringBuilder();
  strBldr.append("Message/nTo: ");
  strBldr.append(to);
  strBldr.append("\nFrom: ");
  strBldr.append(from);
  strBldr.append("\nSubject: ");
  strBldr.append(subject);
  strBldr.append("\n----------------------------------");
  strBldr.append(contents);
  
  return strBldr.toString();
 }
 
 @Override
 public int hashCode()
 {
  final int prime = 31;
  int result = 1;
  result = prime * result
    + ((contents == null) ? 0 : contents.hashCode());
  result = prime * result + ((from == null) ? 0 : from.hashCode());
  result = prime * result
    + ((subject == null) ? 0 : subject.hashCode());
  result = prime * result + ((to == null) ? 0 : to.hashCode());
  return result;
 }
 
 @Override
 public boolean equals(Object obj)
 {
  if (this == obj)
   return true;

  if (obj == null)
   return false;

  if (getClass() != obj.getClass())
   return false;

  Message other = (Message) obj;
  if (contents == null)
  {
   if (other.contents != null)
    return false;
  }
  else if (!contents.equals(other.contents))
   return false;
  
  if (from == null)
  {
   if (other.from != null)
    return false;
  }
  else if (!from.equals(other.from))
   return false;
  
  if (subject == null)
  {
   if (other.subject != null)
    return false;
  }
  else if (!subject.equals(other.subject))
   return false;
  
  if (to == null)
  {
   if (other.to != null)
    return false;
  }
  else if (!to.equals(other.to))
   return false;
  
  return true;
 }
}

Comments

Popular posts from this blog

Implementing Interfaces with Java Records

If you have not read my article on Java records and do not know about this topic, please read my blog titled " Customizing Java Records " first and then come back to this one. Now that you know how to customize Java records, implementing an interface using Java records should be very easy to understand. If you don't know about interfaces in Java, you can read more on my article about interfaces. The recipe for implementing an interface is simply an expansion of what you learned in my previous blog on how to customize a Java record. Following our Rectangle example, let's create an interface with the same two methods we used before. public interface Shape { double area(); double perimeter(); } Now, let's further customize the previous example by doing two things: Add implements Shape at the end of the record declaration (after the record constructor), and Add @Override to the existing methods to ensure these methods com...

Customizing Java Records

If you have not read my article on Java records and do not know about this topic, please read my blog titled " Java Keywords Addendum: The Java Record " first and then come back to this one. What is a customization of a record? A customization of a record is simply the addition of code inside the body of the class. Before proceeding further, let's recap important aspects of a Java Record: Java records are immutable Because of item 1 above, you cannot add new fields unless defined in the record constructor Java records already override: Object#equals(Object) and Object#hashCode() , and then override Object#toString() You could redefine overridden methods as part of your customization if you would like. For example, if you want a fancier implementation of the Object#toString() method, you could do so. Let's look at our first customization example. Using the example from my previous blog, public record Student(...

Object-Oriented Programming Basics: What is in a Class?

EDITORIAL NOTE : This article was published briefly back in 2016 and quickly set back to draft because I wasn't happy with its contents. It is a shame that it was taking me three years to revisit this topic and work on a new and improved version. At least, I'm hoping it will be to the liking you the reader. Keep in mind that the opening paragraph will still read as if I just wrote it for my (former) students at Texas Wesleyan. I started working on lecture on the topic of Object-Oriented (OO) Programming by gathering some material, old and new, when I realized this might be good and simple post for my second attempt at blogging. To be completely honest, in the 8 hours I spent collecting information and preparing material for this week's lecture, I realized I still made some of the mistakes I am about to blog about. I am actually hoping I can write a series of postings regarding Object-Oriented Programming (OOP). But to do so, I must start from the very beginning. ...