JAVA学习(二):如何面向对象

java是一门面向对象的编程语言,那么,什么是面向对象编程?简单点说,就是找合适的对象办合适的事。举个生活中的例子,一个人想要开发一个程序,但是他不会编程,怎么办?他可以选择自己学编程,等学会了,再开发,这是面向过程的做法,特点就是什么都自己亲历亲为,对项目的把控性会比较好,但效率低下。另外一种做法就是,他自己不会编程,那就找一个会编程的人,帮他开发。这是面向对象的做法,特点是很多事并不是自己亲自做,而是找别人代做。这种做法,效率很高,但是对项目的把控性就会有所欠缺。很可能别人做出来的东西,并不是你想要的。

在java里面,应该怎么应用面向对象的编辑思想呢?比如,要做一个用户登录的功能,需求是用户名和密码都是8-16位,应该怎么做这个功能?很多开发人员,都是把用户名和密码的规则判断放到Controller里面,这其实是面向过程的做法。如果要用面向对象的做法,用户名和密码的规则判断,应该放到对象中去。可以定义一个User类,来接收前端传过来的用户名和密码。当我们定义了一个类,这个类的属性,能够接收什么样的数据,在类中就要定义好,这才是最好的逻辑。User类中有属性username,接收前端传过来的用户名,那么在User类的定义中,就可以限定username,必须是8-16位,这样,User类的实例,才是合适的对象。然后在Controller里面,就不需要做判断,把判断交给User类的对象去判断。这就是找合适的对象做合适的事。那么,在代码里,应该怎么来实现这样的功能?

package king;

public class User {

	private String username;
	private String password;

	public String getUsername() {
		return username;
	}
	public void setUsername(String username) {
		if(username == null){
			return;
		}
		username = username.trim();
		if("".equals(username)){
			
		}else if(username.length()<8){
			
		}else if(username.length()>16){
			
		}else{
			this.username = username;
		}
	}
	public String getPassword() {
		return password;
	}
	public void setPassword(String password) {
		if(password == null){
			return;
		}
		password = password.trim();
		if("".equals(password)){
			
		}else if(password.length()<8){
			
		}else if(password.length()>16){
			
		}else{
			this.password = password;
		}
	}
	@Override
	public String toString() {
		return "User [username=" + username + ", password=" + password + "]";
	}
}

这样,类的定义在set方法中就规定了username和password,能够接收什么样的数据,现在的问题是,在前面的那些异常数据的判断里,应该怎么处理?如果数据格式,不符合要求,那肯定要反馈给Controller的,再由Controller,反馈给前端去,怎么反馈?这个时候,就要用到异常机制,如果数据,不符合要求,那就抛出一个异常,但这个异常,和程序中其它的异常又是不一样的,所以这个异常,就应该使用自定义的异常。

package king;

public class KingException extends Exception {

	private static final long serialVersionUID = 1L;

	public KingException(){
		super();
	}
	
	public KingException(String message){
		super(message);
	}
	
}

这样,就有了一个自定义的异常了。然后,在User类的set方法里面,数据不符合要求,就抛出这个异常,代码:

package king;

public class User {

	private String username;
	private String password;

	public String getUsername() {
		return username;
	}
	public void setUsername(String username) throws KingException {
		if(username == null){
			throw new KingException("非法请求!");
		}
		username = username.trim();
		if("".equals(username)){
			throw new KingException("用户名不能为空!");
		}else if(username.length()<8){
			throw new KingException("用户名不能少于8位!");
		}else if(username.length()>16){
			throw new KingException("用户名最多只能有16位!");
		}else{
			this.username = username;
		}
	}
	public String getPassword() {
		return password;
	}
	public void setPassword(String password) throws KingException {
		if(password == null){
			throw new KingException("非法请求!");
		}
		password = password.trim();
		if("".equals(password)){
			throw new KingException("密码不能为空!");
		}else if(password.length()<8){
			throw new KingException("密码不能少于8位!");
		}else if(password.length()>16){
			throw new KingException("密码最多只能有16位!");
		}else{
			this.password = password;
		}
	}
	@Override
	public String toString() {
		return "User [username=" + username + ", password=" + password + "]";
	}
}

那么,在Controller里面,为User类的对象赋值的时候,就要捕获这个异常,然后调用异常的getMessage()方法,把异常的提示语,响应到前端去。

在类中判断数据规则,相比在Controller里面做判断,有什么好处呢?好处,就是代码量会减少,也更好维护。在对象中判断,不但能阻止前端传入的错误数据,也能阻止数据库中错误的数据,进入程序,而且不用重复写代码。如果是写在Controller里面,那么注册帐号,登录,修改密码等,几个接口里面,都要写一套判断逻辑,这就会产生大量的重复代码。而一旦规则更改了,则要修改好几个地方,一不小心,就漏掉一个地方没有修改。想想都觉得可怕!

再来看一个问题,很多时候,我们调用方法,是通过反射来调用的,那么,通过反射调用方法,如何获取方法本身抛出的异常,这个其实也很简单

package king;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class Controller {
	
	public static void main(String[] args) {
		test();
	}
	
	public static void test(){
		User user = new User();
		Class<User> clazz = User.class;
		Method method;
		try {
			method = clazz.getMethod("setUsername", String.class);
			method.invoke(user, "123");
		} catch (NoSuchMethodException e) {
			e.printStackTrace();
		} catch (SecurityException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			Throwable t = e.getTargetException();
			if(t instanceof KingException){
				System.out.println(t.getMessage());
			}
		}
	}
}

重点就在最后面的一个catch里面,通过e.getTargetException(),获取方法本身抛出的异常,先判断一下,如果异常的类型与KingException相符,那么就可以做相应的处理了。如果不相符,那就是程序抛出的其它异常了,这个就可能是程序的bug了,当然,我这里,没有写else分支。执行程序,就会打印:用户名不能少于8位!

再来看用于对象和json转换的jackson包,在对象和json转换的时候,如何获取方法本身的异常

package king;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;

public class Controller {
	
	public static void main(String[] args) throws KingException {
		String json = "{\"username\":\"1223\",\"password\":\"32651\"}";
		ObjectMapper mapper = new ObjectMapper();
		try {
			User user = mapper.readValue(json, User.class);
			System.out.println(user);
		} catch (JsonParseException e) {
			e.printStackTrace();
		} catch (JsonMappingException e) {
			Throwable t = e.getCause();
			if(t instanceof KingException){
				throw (KingException) t;
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
		
	}

}

这里,重点就在倒数第二个catch里面,通过e.getCause()方法,来获取方法自身抛出的异常。

了解了这一些,是不是可以去封装一些属于自己的方法了呢?

欢迎加入测试群:91425817,一起讨论测试的那此事。

发布了47 篇原创文章 · 获赞 9 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/kingzhsh/article/details/89419466
今日推荐