【问题标题】:Why is my exception need to be in try/catch? [closed]为什么我的异常需要在 try/catch 中? [关闭]
【发布时间】:2020-05-18 17:09:03
【问题描述】:

我正在尝试从数据库中获取信息。并检查用户名是否已经存在 我正在使用 google cloud firestore 数据库。 我将该方法声明为抛出我创建的异常。 当我尝试调用抛出异常时,它告诉我需要将其放入 try/catch 块中。 我想知道为什么,因为我做了类似的事情(但是和我的老师一起使用 sqlite 并且效果很好)

我的代码:

@Override
public void isUserExists(final String username, String email) throws UserExistsException {
    Log.e(TAG, "isUserExists: in start of method" );
    // gets the document reference
    CollectionReference usersRef = db.collection(COLLECTION_NAME);
    //Creates and returns a new Query with the additional filter that documents must contain the specified field and the value should be equal to the specified value.
    Query query = usersRef.whereEqualTo(KEY_USERNAME, username);
    //Executes the query and returns the results as a QuerySnapshot.
    // QuerySnapshot = A QuerySnapshot contains the results of a query. It can contain zero or more DocumentSnapshot objects. (is an iterable)
    query.get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
        @Override
        public void onComplete(@NonNull Task<QuerySnapshot> task) {
            Log.e(TAG, "isUserExists: in the onComplete" );
            //A DocumentSnapshot contains data read from a document in your Cloud Firestore database.
            if (task.isSuccessful()) {
                Log.e(TAG, "isUserExists: in the if statement" );
                for (DocumentSnapshot item : task.getResult()) {
                    Log.e(TAG, "isUserExists: in for loop" );
                    //getString() = Returns the value of the field as a String.
                    String user = item.getString(KEY_USERNAME);
                    if (user.equals(username)) {
                      //this throw line will not compile
                        throw new UserExistsException();
                    }
                }
            }
        }
    });
}

我正在实现这个接口:

public interface IUser {

void isUserExists(String username, String email) throws UserExistsException;
void isPassesMatch(String password, String rePass) throws PasswordMismatchException;
void checkLength(String username, String password) throws PasswordLengthException, UserNameLengthException;
void checkUserCred(String username, String password) throws UserCredentialException;
void registerUser (String username, String password, String email) throws UserException;
}

我在课堂上和老师做过的类似的事情:

 @Override
public void userExists() throws UserExistsException {
    String sqlStatement = "SELECT * FROM " + TABLE_NAME + " WHERE userName = '" + this.userName + "'";
    Cursor res = db.rawQuery(sqlStatement, null);
    if(res.moveToFirst()){
        throw new UserExistsException();
    }
}

编辑(添加我抛出的异常):

public class UserExistsException extends UserException {

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

public UserExistsException() {
    super("User Already Exists");
}
}

另一个编辑(添加处理方法及其异常的位置 ):

private void register() {
    String uName = regActEtUname.getText().toString();
    String uPass = regActEtPass.getText().toString();
    String rePass = regActEtRePass.getText().toString();
    String uEmail = regActEtEmail.getText().toString();

    try {
        // checks if the user exissts
        utils.isUserExists(uName,uEmail);
        //checks if the length is fulfilled
        utils.checkLength(uName,uPass);
        //checks if the passwords match
        utils.isPassesMatch(uPass, rePass);
        //registers the user
        utils.registerUser(uName,uPass,uEmail);

    } catch (UserExistsException | PasswordLengthException | UserNameLengthException | PasswordMismatchException e) {
        Log.e("fbdb", "register: " + e.getMessage() );
        TastyToast.makeText(context,e.getMessage(), TastyToast.LENGTH_LONG, TastyToast.ERROR);
    } catch (UserException e) {
        Log.e("regErr", "register: " + e.getMessage() );
    } catch (Exception e) {
        Log.e("regErr", "register: " + e.getMessage() );
    }
}

【问题讨论】:

  • 你在哪一行有问题?
  • 问题有点不清楚,我会回答我所理解的,当你调用一个抛出异常的方法时,你要么需要捕获它并有意义地使用它,要么进一步抛出它。
  • @user2222 我在 isUserExist 方法内的最后一个 if 块中遇到了问题。 @sunil.kms123 我将该方法声明为抛出异常。当我尝试投掷它时,它说我需要将投掷包裹在 try/catch 块中
  • 我看到你把它扔进了 onComplete 方法而不是 isUserExists 方法;我认为您应该在 onComplete 方法中添加 try catch bock 来处理该异常,因为仅当被覆盖的方法也抛出相同的异常时,被覆盖的方法(在您的情况下为 onComplete)才能抛出异常。从java的角度来看,因为我对android知之甚少,所以可能有更好的解决方法。
  • 你老师的例子很好,因为异常是在 userExists() 方法中抛出的

标签: java android exception google-cloud-firestore try-catch


【解决方案1】:

我建议在 isUserExists 方法中使用布尔变量,我们可以在 onComplete 方法中更新该变量并依靠它来抛出或不抛出 UserExistsException。

@Override
public void isUserExists(final String username, String email) throws UserExistsException {
    Log.e(TAG, "isUserExists: in start of method" );
    boolean isUserExist = false;
    // gets the document reference
    CollectionReference usersRef = db.collection(COLLECTION_NAME);
    //Creates and returns a new Query with the additional filter that documents must contain the specified field and the value should be equal to the specified value.
    Query query = usersRef.whereEqualTo(KEY_USERNAME, username);
    //Executes the query and returns the results as a QuerySnapshot.
    // QuerySnapshot = A QuerySnapshot contains the results of a query. It can contain zero or more DocumentSnapshot objects. (is an iterable)
    query.get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
        @Override
        public void onComplete(@NonNull Task<QuerySnapshot> task) {
            Log.e(TAG, "isUserExists: in the onComplete" );
            //A DocumentSnapshot contains data read from a document in your Cloud Firestore database.
            if (task.isSuccessful()) {
                Log.e(TAG, "isUserExists: in the if statement" );
                for (DocumentSnapshot item : task.getResult()) {
                    Log.e(TAG, "isUserExists: in for loop" );
                    //getString() = Returns the value of the field as a String.
                    String user = item.getString(KEY_USERNAME);
                    if (user.equals(username)) {
                      isUserExist = true;
                    }
                }
            }
        }
    });
    if (isUserExist) throw new UserExistsException();
}

【讨论】:

  • 它仍然使用相同的用户名注册用户,它工作,现在它没有。
【解决方案2】:

试试这个代码:

@Override
public void isUserExists(final String username, String email) throws 
 UserExistsException {

     CollectionReference allUsersRef = db.collection(COLLECTION_NAME);
     Query userNameQuery = allUsersRef.whereEqualTo(KEY_USERNAME, username);
     userNameQuery.get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
       @Override
       public void onComplete(@NonNull Task<QuerySnapshot> task) {
          if (task.isSuccessful()) {
               for (DocumentSnapshot document : task.getResult()) {
                  if (document.exists()) {
                     String userName = document.getString(username);
                     Log.d(TAG, "username already exists");
                  } else {
                     Log.d(TAG, "username does not exists");
                  }
               }
          } else {
             Log.d("TAG", "Error getting documents: ", task.getException());
          }
      }
    });
}

如果对你有帮助,请告诉我。

【讨论】:

  • 我对其进行了一些修改以更适合我的代码和我的工作方式,但它确实有效。谢谢 :)。我只有一个问题,这段代码有效吗?我的意思是,如果我有 500,000 个或更多帐户,是否需要很长时间才能返回答案?我知道你使用 whereEqualTo,但你也运行了一个循环。
  • 您能否分享一下您的 Firestore 的结构,看看是否有更好的方法来做同样的事情?我知道您有一个集合,在该集合中您有一些文档,如果用户存在与否,您想查看文档,对吗?如果我理解错了,请纠正我。
  • 你没看错,我有主集合 -> 文档 -> 文档字段,我想检查这些字段。我只是问这段代码是否会遍历所有文档。
  • 是的,它将遍历所有文档。
  • 感谢您接受我的回答。
猜你喜欢
  • 1970-01-01
  • 2011-09-23
  • 1970-01-01
  • 1970-01-01
  • 2014-11-07
  • 1970-01-01
  • 1970-01-01
  • 2019-01-07
  • 1970-01-01
相关资源
最近更新 更多