Мен ақыр соңында blcok-те тырнақшаны қолданбаймын. (java)

Міне, кейбір Java кодтары.

public class SomeClass {
private Connection connection;

public SomeClass(Connection c) {
    connection = c;
}
public void someWork(){
    Connection c;
    try {
       //do something
    } catch (Exception e) {
       //some exception code
    } finally {
        if (conn != null){
            try {c.close();} catch (Exception e) {}
        }
    }
}

}

бірақ кодты ұнатпаймын

if (conn != null){
        try {c.close();} catch (Exception e) {}
    }

сондықтан кодты ойлаймын

...catch (Exception e) {
       //some exception code
    } finally {
        c = null;
    }

бірақ «Ағынды ағынды емес қоқыс жинау» нысанын көремін.

Мен ақыр соңында блокта тырнақшаны қолданбаймын. Маған басқаша жол беріңізші.

0
Ең бастысы, неге сіз ерекше жағдайды елемейсіз бе? Әр жолы мен тек қана тырысып көруге тырысып көремін. Кейінірек отладтан кейін біреудің өмірін қиындатады.
қосылды автор Paddy, көзі
Неліктен сіз? Шынымды айтсам, басқа тілге салынған тіл құрылысын ерікті түрде тыйым салудың себебін көре алмаймын.
қосылды автор michaelb958, көзі

7 жауаптар

Статикалық утилита әдісін жасаңыз:

private static void closeQuietly(final Connection conn)
{
    if (conn == null)
        return;
    try {
        conn.close();
    } catch (WhateverException ignored) {
    }
}

Содан кейін

conn = whatever();//create it there, not in the try block
try {
   //work
} catch (WhateverException e) {
   //whatever
} finally {
    closeQuietly(conn);
}

Бірақ, сайып келгенде, сіз болады , сайып келгенде блокта try/catch ұстаңыз.

Exception аулау жаман идея болып табылады. Оның орнына conn.close() арқылы шығарылған ерекше жағдайларды ұстаңыз. Exception тәрізді ұстау сіз барлық RuntimeException -ның барлық түрлерін ұстауыңызды білдіреді; және бұл Bad Thing (tm).

Егер сіз Guava-ды пайдалансаңыз, сіз Closeables.closeQuietly() , бұл жоғарыда көрсетілген код сияқты бірдей нәрсе. Сіз сондай-ақ Closer , бұл өте қызықты.

Ақырында (жазылған): егер сіз Java 7-ді қолдансаңыз, орнына «try-with-resource» сөзін пайдаланыңыз (қараңыз: AutoCloseable ):

try (
    conn = whatever();
) {
   //...
}
6
қосылды
Мен Exception ұстап алсаңыз, сізде де жұмыс үрдісімен ешқандай қатысы жоқ ерекше жағдайларды табасыз.
қосылды автор fge, көзі
ақпарат үшін рахмет. Мен өзімнің орта туралы жаза аламын. Мен jdk 6-ді қолданамын, бірақ шын мәнінде әрбір жағдайды алып тастаудың қандай да бір себептері жоқ. Мен әдетте Exception e және e.printStackTrace() қолданамын, содан кейін бұл java.sql.SQLException сияқты жұмыс істейді: ORA-00936: oracle.jdbc өрнегі жоқ. driver.DatabaseError.throwSqlException (DatabaseE & zwnj; rror.java:138) шын мәнінде оның жаман жолы деп ойлайсыз ба? Менің ойымша, мен не екенін және қай жерде екенін білемін.
қосылды автор user2503993, көзі

Сізге бұл код ұнауы мүмкін, бірақ бұл жағдайда қажет. (Коды @ fge-ның closeQuietly әдісі сияқты орап алуға болады.)

But there is a more fundamental problem. Changing someWork to close the connection in a finally block is not sufficient to prevent a leak ... in this situation!!

Неліктен?

Мынаны қарастырайық:

SomeClass sc = new SomeClass(createConnection());
// do some stuff
sc.someWork();

1-сұрақ: «Кейбір заттар жасау» кодының ерекше жағдайына алып тасталса, не болады?

2-сұрақ: SomeClass құрып, құру кезінде ерекше жағдай туындаса не болады? (Ескерту: бұл ең қарапайым конструкторлармен бірге мүмкін, мысалы, OOME new операциясы арқылы тасталуы мүмкін ...)

Жауап: Қосылу нысаны екі негізде де ағады!


Түзету ресурсты (мысалы, Connection object) ішіне немесе try/catch/соңына дейін бөлу; мысалы,

Connection c = createConnection();
try {
   //do something
} catch (SomeException e) {
   //some exception code
} finally {
    if (c != null){
        try {c.close();} catch (SomeException e) {}
    }
}

Java 7-де келесідей жаза аласыз:

try (Connection c = createConnection()) {
   //do something
} catch (SomeException e) {
   //some exception code
}

Connection AutoCloseable интерфейсін жүзеге асырған жағдайда. Java 7 нұсқасы - close() деп аталатын және кез келген алынған ерекше жағдайларды ақылмен шешетін null үшін тексеруді қамтамасыз ететін күрделі іске қосу үшін «синтаксистік қант». (JLS шын мәнінде «ресурспен жұмыс істеуге тырысу» туралы мәліметтер береді.)


Жазба үшін:

  • The issue is not garbage collection/collecting. The issue is that the Connection object needs to be closed.

  • Assigning null won't cause an object to be closed. It won't even cause it to be garbage collected. At best, it can make the object eligible for garbage collection ... in some future GC run.

  • Catching Exception is a really bad idea. Read this: Need authoritative source for why you shouldn't throw or catch java.lang.Exception

1
қосылды
@ user2503993 - Бұл бақытсыз. Бірақ егер сіз тілді ескірген нұсқасын қолданғыңыз келсе, оның шектеулілігін көтеру керек. «Ұнайды» үйреніңіз.
қосылды автор Stephen C, көзі
@ user2503993 - Сондай-ақ, Java 6-ның EOLd болғанын (AND BOSS/CLIENTS) Басқа қауіпсіздік жаңартулары жоқ ... егер ол Oracle Java қолдау келісімін шығармаса. java.com/en/download/faq/java_6.xml
қосылды автор Stephen C, көзі
Кешіріңіз jdk 6 пайдаланыңыз.
қосылды автор user2503993, көзі

Осыған байланысты тағы бір жұмыс әдіс ішіндегі тұтқаны алып тастау:

public void someWork() throws SQLException{
    Connection c;
    try {
       //do something
    } finally {
        if (conn != null){
            c.close();
        }
    }
}

Содан кейін, сіз someWork әдісін шақырған негізгі әдіске әдісті тыс тексеруді жасайсыз немесе оны someWork() деп аталатын басқа әдіске орап аласыз:

 public void callSomeWork(){
    try{
     someWork();
    }catch(SQLException ex){
    //handle SQL error here
    }
 }

Осылайша қате жіберілген қате немесе бір SQLException ішінде жарияланады.

1
қосылды

Егер сіз өшірсеңіз және жабылмаған болсаңыз, барлық әдістер әрдайым жаңа ашық қосылымға ие болатынын тексеріңіз.

Сіз білуі қажет жалғыз нәрсе - сіз кез-келген уақытта сіз керек байланысын жабуыңыз керек (демек, соңында блок), ал бұл қосылымды қосымшада ашық қалдыра аласыз және ақыр соңында қол жетімді байланыстардың аяқталуы мүмкін.

0
қосылды

Себебі Java 7 бұл болар еді

try (Connection conn = DriverManager.getConnection(props)) {
    ...
}

Java 7 алдында

Connection conn = DriverManager.getConnection();
try {
  ...
} finally {
    conn.close();
}
0
қосылды

Жабық емес және NULL мәніне орнатылған болса, зомби қосылымын қалдыруыңыз мүмкін.

0
қосылды

басқа біреуді сынап көруге рұқсат етіңіз және Apache Commons IOUtile

closeQuietly() -methods бірі (мысалы, this one ) сізге қажет нәрсе болуы керек:

Кез келген қоспағанда, InputStream.close() үшін теңдестірілмейтін болады. Бұл   әдетте блоктарда қолданылады.

0
қосылды