我想在使用Jackson 1.9反序列化特定类型时运行一些自定义代码.但是,我不想手写整个反序列化器,只需添加到默认行为.但是,尝试以JsonDeserializer天真的方式执行此操作会导致无限递归.目前,我的方法使用完全独立ObjectMapper,但感觉就像一个巨大的黑客.
private static class SpecialDeserializer extends JsonDeserializer<Special> {
@Override
public Special deserialize(JsonParser jp, DeserializationContext ctxt)
throws IOException, JsonProcessingException {
JsonNode jsonNode = jp.readValueAsTree();
ObjectMapper otherMapper = getOtherMapper();
Special special = otherMapper.readValue(jsonNode, Special.class);
special.setJsonNode(jsonNode);
return special;
}
}
Run Code Online (Sandbox Code Playgroud) 它似乎getAnnotatedParameterTypes()返回一个包含AnnotatedType原始类型而不是泛型类型的s 数组.例如:
public <T> void genericMethod(T t) {
}
@Test
public void testAnnotatedTypes() throws ReflectiveOperationException {
Method method = getClass().getMethod("genericMethod", Object.class);
Type type = method.getGenericParameterTypes()[0];
assertTrue(type instanceof TypeVariable);
AnnotatedType annotatedType = method.getAnnotatedParameterTypes()[0];
// This fails; annotatedType implements only AnnotatedType
assertTrue(annotatedType instanceof AnnotatedTypeVariable);
// This fails too; type is a TypeVariable while annotatedType.getType() is
// Object.class
assertEquals(type, annotatedType.getType());
}
Run Code Online (Sandbox Code Playgroud)
分歧的原因是什么getGenericParameterTypes()?
C++ 11引入了统一初始化,它具有禁止隐式缩小转换的理想特性.例如,int i{2.2}应该是一个错误.
不幸的是,出于向后兼容性的原因,C++ 03,GCC从4.7开始只给出了这些警告.
GCC的文档表明此扩展不适用于SFINAE环境,但它似乎是错误的:
#include <type_traits>
#include <utility>
template <typename From, typename To>
class is_list_convertible_helper
{
template <typename To2>
static void requires_conversion(To2 t);
template <typename From2, typename To2,
typename = decltype(requires_conversion<To2>({std::declval<From2>()}))>
// ^ Braced initializer
static std::true_type helper(int);
template <typename From2, typename To2>
static std::false_type helper(...);
public:
using type = decltype(helper<From, To>(0));
};
template <typename From, typename To>
class is_list_convertible
: public is_list_convertible_helper<From, To>::type
{ };
static_assert(!is_list_convertible<double, int>::value,
"double -> int is narrowing!");
Run Code Online (Sandbox Code Playgroud)
GCC …
我的理解是这样的事情是可以的:
const int ci = 42;
const int *cip = &ci;
int *ip = (int *)cip;
int j = *ip;
Run Code Online (Sandbox Code Playgroud)
那这个呢?
const int ci = 42;
const int *cip = &ci;
const int **cipp = &cip;
int **ipp = (int **)cipp;
int j = **ipp;
Run Code Online (Sandbox Code Playgroud) 根据cppreference.com,std :: vector :: emplace()无条件地提供强大的异常保证:
如果抛出异常(例如,通过构造函数),则容器保持不变,就好像从未调用此函数一样(强异常保证).
但是,GCC 7.1.1在实践中似乎并非如此.以下程序:
#include <iostream>
#include <vector>
struct ugly
{
int i;
ugly(int i) : i{i} { }
ugly(const ugly& other) = default;
ugly& operator=(ugly&& other) {
if (other.i == 3) {
throw other.i;
}
i = other.i;
return *this;
}
ugly& operator=(const ugly& other) = default;
};
int main() {
std::vector<ugly> vec;
vec.reserve(6);
vec.emplace_back(0);
vec.emplace_back(1);
vec.emplace_back(2);
vec.emplace_back(4);
vec.emplace_back(5);
try {
vec.emplace(vec.begin() + 3, 3);
} catch (int i) {
}
for (const auto& …Run Code Online (Sandbox Code Playgroud) gcc -dumpmachine几乎是完美的,但它不尊重影响目标的旗帜.另一方面,clang确实:
$ gcc -dumpmachine
x86_64-unknown-linux-gnu
$ gcc -dumpmachine -m32
x86_64-unknown-linux-gnu
Run Code Online (Sandbox Code Playgroud)
$ clang -dumpmachine
x86_64-unknown-linux-gnu
$ clang -dumpmachine -m32
i386-unknown-linux-gnu
Run Code Online (Sandbox Code Playgroud) 假设我有一个可以异步运行某些代码的类,并且该异步代码使用该类实例来执行调用成员函数,读取数据成员等操作.显然,类实例必须比后台线程更长,以便进行这些访问.安全.通过在析构函数中加入后台线程来确保这一点就足够了吗?例如:
#include <iostream>
#include <thread>
class foo final
{
public:
foo() = default;
void bar() {
std::cout << "Hopefully there's nothing wrong with using " << this << "\n";
}
void bar_async() {
if (!m_thread.joinable()) {
m_thread = std::thread{&foo::bar, this};
}
}
~foo() {
if (m_thread.joinable()) {
std::cout << "Waiting for " << m_thread.get_id() << "\n";
m_thread.join();
}
}
private:
std::thread m_thread;
};
int main() {
foo f;
f.bar_async();
}
Run Code Online (Sandbox Code Playgroud)
具体来说,我担心对象生存期规则:
对于析构函数不是微不足道的类类型的任何对象,生命周期在析构函数的执行开始时结束.
...在对象的生命周期结束之后,在重用或释放对象占用的存储之前,以下使用标识该对象的glvalue表达式是未定义的:...
- 访问非静态数据成员或调用非静态成员函数.
但对我来说,严格阅读上述内容也意味着this->bar()从内部~foo() …
此代码导致javac编译错误(但值得注意的是,不是Eclipse 4.2.2!):
public interface Foo<T> {
}
class Bar<T> implements Foo<Iterable<T>> {
}
class Test {
void test(Foo<? extends Iterable<? extends String>> foo) {
Bar<?> bar = (Bar<?>) foo;
}
}
Run Code Online (Sandbox Code Playgroud)
来自javac的错误是这样的:
Foo.java:9: error: inconvertible types
Bar<?> bar = (Bar<?>) foo;
^
required: Bar<?>
found: Foo<CAP#1>
where CAP#1 is a fresh type-variable:
CAP#1 extends Iterable<? extends String> from capture of ? extends Iterable<? extends String>
Run Code Online (Sandbox Code Playgroud)
将转换更改为(Bar) foo(即使用原始类型)允许代码编译,就像更改类型一样foo简单Foo<? extends Iterable<?>>.
编辑:非常有趣,这个简单的改变导致Eclipse拒绝,但javac接受:
void test(Foo<Iterable<String>> foo) { …Run Code Online (Sandbox Code Playgroud) 为什么以下代码无法编译?
interface Iface<T> { }
class Impl<T> implements Iface<T> { }
class TestCase {
static Class<? extends Iface<?>> clazz = Impl.class;
}
Run Code Online (Sandbox Code Playgroud)
错误是
java:不兼容的类型:
java.lang.Class<Impl>无法转换为java.lang.Class<? extends Iface<?>>
但我不明白为什么通配符不能捕获.
当使用clang 3.5.0和-flto并使用共享库进行链接时,共享库中的调用似乎operator delete不会遵循与operator new主对象的调用相同的符号解析顺序.例:
shared.cpp:
void deleteIt(int* ptr) {
delete ptr;
}
Run Code Online (Sandbox Code Playgroud)
main.cpp:
#include <cstdlib>
#include <new>
void* operator new(size_t size) {
void* result = std::malloc(size);
if (result == nullptr) {
throw std::bad_alloc();
}
return result;
}
void operator delete(void* ptr) noexcept {
std::free(ptr);
}
void deleteIt(int* ptr);
int main() {
deleteIt(new int);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这是我构建它并通过valgrind运行时会发生的事情:
$ clang++ -std=c++11 -g -O3 -flto -fuse-ld=gold -fPIC -shared shared.cpp -o libshared.so
$ clang++ -std=c++11 -g -O3 …Run Code Online (Sandbox Code Playgroud)