Когда вы объявляете ссылочную переменную (т. е. объект), вы действительно создаете указатель на объект. Рассмотрим следующий код, в котором вы объявляете переменную примитивного типа int
:
int x;
x = 10;
В этом примере переменная x является int
, и Java инициализирует ее для 0. Когда вы назначаете его 10 во второй строке, ваше значение 10 записывается в ячейку памяти, на которую указывает x.
Но когда вы пытаетесь объявить ссылочный тип, произойдет что-то другое. Возьмите следующий код:
Integer num;
num = new Integer(10);
Первая строка объявляет переменную с именем num
, но она не содержит примитивного значения. Вместо этого он содержит указатель (потому что тип Integer
является ссылочным типом). Поскольку вы еще не указали, что указать на Java, он устанавливает значение null, что означает «Я ничего не указываю».
Во второй строке ключевое слово new
используется для создания экземпляра (или создания ) объекту типа Integer и переменной указателя num
присваивается этот объект. Теперь вы можете ссылаться на объект, используя оператор разыменования .
(точка).
Exception
, о котором вы просили, возникает, когда вы объявляете переменную, но не создавали объект. Если вы попытаетесь разыменовать num
. Перед созданием объекта вы получите NullPointerException
. В самых тривиальных случаях компилятор поймает проблему и сообщит вам, что «num не может быть инициализирован», но иногда вы пишете код, который непосредственно не создает объект.
Например, вы можете имеют следующий метод:
public void doSomething(SomeObject obj) {
//do something to obj
}
В этом случае вы не создаете объект obj
, скорее предполагая, что он был создан до вызова метода doSomething
. К сожалению, этот метод можно вызвать следующим образом:
doSomething(null);
В этом случае obj
имеет значение null. Если метод предназначен для того, чтобы что-то сделать для переданного объекта, целесообразно бросить NullPointerException
, потому что это ошибка программиста, и программисту понадобится эта информация для целей отладки.
Альтернативно, там могут быть случаи, когда цель метода заключается не только в том, чтобы работать с переданным в объекте, и поэтому нулевой параметр может быть приемлемым. В этом случае вам нужно будет проверить нулевой параметр и вести себя по-другому. Вы также должны объяснить это в документации. Например, doSomething
может быть записано как:
/**
* @param obj An optional foo for ____. May be null, in which case
* the result will be ____.
*/
public void doSomething(SomeObject obj) {
if(obj != null) {
//do something
} else {
//do something else
}
}
Наконец, Как определить исключение & amp; причина использования Трассировки стека
Вот как я это делаю с современным синтаксисом, основанным на примере go-oleg.
Я добавил несколько комментариев в код.
./ db / mongodb.js
blockquote>< blockquote>const MongoClient = require('mongodb').MongoClient const uri = 'mongodb://user:password@localhost:27017/dbName' let _db const connectDB = async (callback) => { try { MongoClient.connect(uri, (err, db) => { _db = db return callback(err) }) } catch (e) { throw e } } const getDB = () => _db const disconnectDB = () => _db.close() module.exports = { connectDB, getDB, disconnectDB }
./ index.js
blockquote>// Load MongoDB utils const MongoDB = require('./db/mongodb') // Load queries & mutations const Users = require('./users') // Improve debugging process.on('unhandledRejection', (reason, p) => { console.log('Unhandled Rejection at:', p, 'reason:', reason) }) const seedUser = { name: 'Bob Alice', email: 'test@dev.null', bonusSetting: true } // Connect to MongoDB and put server instantiation code inside // because we start the connection first MongoDB.connectDB(async (err) => { if (err) throw err // Load db & collections const db = MongoDB.getDB() const users = db.collection('users') try { // Run some sample operations // and pass users collection into models const newUser = await Users.createUser(users, seedUser) const listUsers = await Users.getUsers(users) const findUser = await Users.findUserById(users, newUser._id) console.log('CREATE USER') console.log(newUser) console.log('GET ALL USERS') console.log(listUsers) console.log('FIND USER') console.log(findUser) } catch (e) { throw e } const desired = true if (desired) { // Use disconnectDB for clean driver disconnect MongoDB.disconnectDB() process.exit(0) } // Server code anywhere above here inside connectDB() })
./ users / index.js
blockquote>const ObjectID = require('mongodb').ObjectID // Notice how the users collection is passed into the models const createUser = async (users, user) => { try { const results = await users.insertOne(user) return results.ops[0] } catch (e) { throw e } } const getUsers = async (users) => { try { const results = await users.find().toArray() return results } catch (e) { throw e } } const findUserById = async (users, id) => { try { if (!ObjectID.isValid(id)) throw 'Invalid MongoDB ID.' const results = await users.findOne(ObjectID(id)) return results } catch (e) { throw e } } // Export garbage as methods on the Users object module.exports = { createUser, getUsers, findUserById }
Вы можете создать модуль mongoUtil.js
, который имеет функции как для подключения к mongo, так и для возврата экземпляра mongo db:
var MongoClient = require( 'mongodb' ).MongoClient;
var _db;
module.exports = {
connectToServer: function( callback ) {
MongoClient.connect( "mongodb://localhost:27017/marankings", function( err, db ) {
_db = db;
return callback( err );
} );
},
getDb: function() {
return _db;
}
};
Чтобы использовать его, вы сделаете это в своем app.js
:
var mongoUtil = require( 'mongoUtil' );
mongoUtil.connectToServer( function( err ) {
// start the rest of your app here
} );
И тогда, когда вам нужен доступ к mongo где-нибудь, вы можете сделать это:
var mongoUtil = require( 'mongoUtil' );
var db = mongoUtil.getDb();
db.collection( 'users' ).find();
Причина этого в том, что в узле, когда модули require
'd, они только загружаются / получаются один раз, так что вы только когда-нибудь закончите с одним экземпляром _db
, а mongoUtil.getDb()
всегда вернет тот же самый экземпляр.
Примечание, код не проверен.
app.js
в функции обратного вызова из connectToServer
. Если вы require
их в app.js
до _db
установлены, то вы получите неопределенные ошибки в других модулях.
– Mike
17 February 2018 в 22:40
go-oleg в принципе прав, но в эти дни вы (вероятно) не хотите использовать «mongodb» самостоятельно, скорее используйте некоторую фреймворк, которая сделает для вас много «грязной работы».
Например, мангуст является одним из самых распространенных. Это то, что мы имеем в нашем исходном файле server.js
:
const mongoose = require('mongoose');
const options = {server: {socketOptions: {keepAlive: 1}}};
mongoose.connect(config.db, options);
Это все, что необходимо для его настройки. Теперь используйте это в любом месте вашего кода
const mongoose = require('mongoose');
И вы получите тот экземпляр, который вы установили с помощью mongoose.connect
Если вы используете Express, то вы можете использовать модуль express-mongo-db , который позволяет вам получить соединение db в объекте запроса.
Установить
npm install --save express-mongo-db
server.js
var app = require('express')();
var expressMongoDb = require('express-mongo-db');
app.use(expressMongoDb('mongodb://localhost/test'));
routes / users.js
app.get('/', function (req, res, next) {
req.db // => Db object
});
Проверенное решение на основе принятого ответа:
mongodbutil.js:
var MongoClient = require( 'mongodb' ).MongoClient;
var _db;
module.exports = {
connectToServer: function( callback ) {
MongoClient.connect( "<connection string>", function( err, client ) {
_db = client.db("<collection name>");
return callback( err );
} );
},
getDb: function() {
return _db;
}
};
app.js :
var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
var app = express();
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
var mongodbutil = require( './mongodbutil' );
mongodbutil.connectToServer( function( err ) {
//app goes online once this callback occurs
var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');
var companiesRouter = require('./routes/companies');
var activitiesRouter = require('./routes/activities');
var registerRouter = require('./routes/register');
app.use('/', indexRouter);
app.use('/users', usersRouter);
app.use('/companies', companiesRouter);
app.use('/activities', activitiesRouter);
app.use('/register', registerRouter);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
next(createError(404));
});
// error handler
app.use(function(err, req, res, next) {
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
res.status(err.status || 500);
res.render('error');
});
//end of calback
});
module.exports = app;
activities.js - маршрут:
var express = require('express');
var router = express.Router();
var mongodbutil = require( '../mongodbutil' );
var db = mongodbutil.getDb();
router.get('/', (req, res, next) => {
db.collection('activities').find().toArray((err, results) => {
if (err) return console.log(err)
res.render('activities', {activities: results, title: "Activities"})
});
});
router.post('/', (req, res) => {
db.collection('activities').save(req.body, (err, result) => {
if (err) return console.log(err)
res.redirect('/activities')
})
});
module.exports = router;