Нет абсолютно никакого различия между использованием статического инициализатора и ленивой инициализацией. На самом деле намного легче испортить ленивую инициализацию, которая также осуществляет синхронизацию. JVM гарантирует, что статический инициализатор всегда выполняется, прежде чем к классу получают доступ, и это произойдет однажды и только однажды.
, Который сказал, JVM не гарантирует, что Ваш класс будет загружен только однажды. Однако, даже если это будет загружено несколько раз, Ваше веб-приложение будет все еще видеть только соответствующий одиночный элемент, поскольку это будет загружено или в веб-приложении classloader или в его родителе. Если у Вас будет несколько развернутых веб-приложений, то в первый раз () будет назван однажды для каждого приложения.
самые очевидные вещи проверить состоят в том, который в первый раз () должен синхронизироваться и что новый флаг установлен прежде, чем выйти из того метода.
Используйте boost :: lexical_cast . Если преобразование не может быть выполнено, оно вызовет исключение .
#include <boost/lexical_cast.hpp>
#include <iostream>
#include <string>
int main(void)
{
std::string s;
std::cin >> s;
try
{
int i = boost::lexical_cast<int>(s);
/* ... */
}
catch(...)
{
/* ... */
}
}
Без повышения:
#include <iostream>
#include <sstream>
#include <string>
int main(void)
{
std::string s;
std::cin >> s;
try
{
std::stringstream ss(s);
int i;
if ((ss >> i).fail() || !(ss >> std::ws).eof())
{
throw std::bad_cast();
}
/* ... */
}
catch(...)
{
/* ... */
}
}
Подделка повышения:
#include <iostream>
#include <sstream>
#include <string>
template <typename T>
T lexical_cast(const std::string& s)
{
std::stringstream ss(s);
T result;
if ((ss >> result).fail() || !(ss >> std::ws).eof())
{
throw std::bad_cast();
}
return result;
}
int main(void)
{
std::string s;
std::cin >> s;
try
{
int i = lexical_cast<int>(s);
/* ... */
}
catch(...)
{
/* ... */
}
}
Если вам нужны версии этих функций без выброса, вам придется перехватить соответствующие исключения (я не думаю, что boost :: lexical_cast
обеспечивает версию без выброса), примерно так:
#include <iostream>
#include <sstream>
#include <string>
template <typename T>
T lexical_cast(const std::string& s)
{
std::stringstream ss(s);
T result;
if ((ss >> result).fail() || !(ss >> std::ws).eof())
{
throw std::bad_cast();
}
return result;
}
template <typename T>
bool lexical_cast(const std::string& s, T& t)
{
try
{
// code-reuse! you could wrap
// boost::lexical_cast up like
// this as well
t = lexical_cast<T>(s);
return true;
}
catch (const std::bad_cast& e)
{
return false;
}
}
int main(void)
{
std::string s;
std::cin >> s;
int i;
if (!lexical_cast(s, i))
{
std::cout << "Bad cast." << std::endl;
}
}
Другие ответы, использующие потоки, будут успешными, даже если строка содержит недопустимые символы после допустимого числа, например, «123abc». Я не знаком с бустом, поэтому не могу комментировать его поведение.
Если вы хотите узнать, содержит ли строка число или только число, вы должны использовать strtol:
#include <iostream>
#include <string>
int main(void)
{
std::string s;
std::cin >> s;
char *end;
long i = strtol( s.c_str(), &end, 10 );
if ( *end == '\0' )
{
// Success
}
else
{
// Failure
}
}
strtol возвращает указатель на символ, завершивший синтаксический анализ, поэтому вы можете легко проверить, была ли вся строка parsed.
Обратите внимание, что strtol возвращает long, а не int, но в зависимости от вашего компилятора они, вероятно, будут одинаковыми. В стандартной библиотеке нет функции strtoi, только atoi, которая не возвращает символ окончания синтаксического анализа.
Другой способ использования стандартных потоков:
#include <sstream>
#include <iostream>
#include <string>
int main()
{
std::stringstream convertor;
std::string numberString = "Not a number!";
int number;
convertor << numberString;
convertor >> number;
if(convertor.fail())
{
// numberString is not a number!
std::cout << "Not a Number!";
}
}
До того, как было доступно lexical_cast
Boost, я делал следующее:
namespace detail {
template< typename Target, typename Source >
struct stream_caster {
static Target stream_cast(const Source& s)
{
std::stringstream ss;
if( (ss << s).fail() ) {
throw std::bad_cast("could not stream from source");
}
Target t;
if( (ss >> t).fail() || !(ss >> ws).eof) {
throw std::bad_cast("could not stream to target");
}
return t;
}
};
template< typename T >
struct stream_caster<T,T> {
static const T& stream_cast(const T& s)
{
return s;
}
};
template< typename Source >
struct stream_caster<std::string,Source> {
static std::string stream_cast(const Source& s)
{
std::ostringstream oss;
if( (oss << s).fail() ) {
throw std::bad_cast("could not stream from source");
}
return oss.str();
}
};
template< typename Target >
struct stream_caster<Target,std::string> {
static Target stream_cast(const std::string& s)
{
std::stringstream ss(s);
Target t;
if( (ss >> t).fail() || !(ss >> ws).eof) {
throw std::bad_cast("could not stream to target");
}
return t;
}
};
template<>
struct stream_caster<std::string,std::string> {
static const std::string& stream_cast(const std::string& s)
{
return s;
}
};
}
template< typename Target, typename Source >
inline Target stream_cast(const Source& s)
{
return detail::stream_caster<Target,Source>::stream_cast(s);
}