论坛首页 Java企业应用论坛

【解惑】JVM如何理解Java泛型类

浏览 18158 次
该帖已经被评为精华帖
作者 正文
   发表时间:2009-12-17  
public class TestFan {

	/**
	 * @param args
	 * 
	 * User是一个空class
	 */
	public static void main(String[] args) {
		int i = 0;
		test(null);
	}

	//
	//不添加此方法.编译,运行没问题.输出显示调用的user
	//添加此方法时候.编译期出错The method test(String) is ambiguous for the type TestFan
	public static void test(String str)
	{
		System.out.println("string");
	}
	
	
	public static void test(User users)
	{
		System.out.println("user");
	}
	
	public static void test(Object users)
	{
		System.out.println("object");
	}
}


请教下:
1.没添加那个方法时候.为什么调用的会是user的那个方法?
2.添加后为什么出错了
0 请登录后投票
   发表时间:2009-12-17  
Heart.X.Raid 写道

class CM<MediaBean>有问题:

首先你要搞清楚你想要定义的类型是泛型类还是普通类。

如果是普通类,class CM implements ConvertMachine<MediaBean>就可以了。
如果是泛型类,正如你定义的一样CM<MediaBean>,编译器会把MediaBean理解为类型变量,相当于常用的T,S,K,V之类的符号。

既然编译器已经认定你定义的class CM<MediaBean>是一个泛型类,而且MediaBean是泛型变量的话。那么编译器理解MediaBean bean 也就认为相当于T bean。试问MediaBean(也就是T)在编译阶段不能够确定具体类型的情况下,MediaBean.getOffset()方法在哪里(也就相当于T.getOffset()方法)。
因此,编译器报错:The method getOffset() is undefined for the type MediaBean

注意,你定义的时候MediaBean已经是CM泛型类的类型变量了,再也不是你认为的某一个类了。一定要保持清醒。


我大概明白了,但是如果是这样的那具体的实现类都不能用泛型来检验编译时错误,只定义接口范围的泛型没什么意义啊。

实际上针对这种情况

public class A<T> extends B<T>{
    void method(T param){
        //do somthing
    }
}


T param 等同于

final T param


局限性很大啊
0 请登录后投票
   发表时间:2009-12-17  
msnvip 写道
public class TestFan {

	/**
	 * @param args
	 * 
	 * User是一个空class
	 */
	public static void main(String[] args) {
		int i = 0;
		test(null);
	}

	//
	//不添加此方法.编译,运行没问题.输出显示调用的user
	//添加此方法时候.编译期出错The method test(String) is ambiguous for the type TestFan
	public static void test(String str)
	{
		System.out.println("string");
	}
	
	
	public static void test(User users)
	{
		System.out.println("user");
	}
	
	public static void test(Object users)
	{
		System.out.println("object");
	}
}


请教下:
1.没添加那个方法时候.为什么调用的会是user的那个方法?
2.添加后为什么出错了



我觉得这可能是编译器的默认行为吧 默认
Object , ? extends Object 


类似多态?

2个子类,编译器识别不了了。。。
0 请登录后投票
   发表时间:2009-12-18  
我就想知道你是如何看到的JVM的源代码,可以和je分享一下么?谢谢
0 请登录后投票
   发表时间:2009-12-18  
mali0330 写道
我就想知道你是如何看到的JVM的源代码,可以和je分享一下么?谢谢


JDK 工具包里面都有一个src文件,里面是source code,但native方法,与虚拟机相关的部分没有公开。
0 请登录后投票
   发表时间:2009-12-18  
Heart.X.Raid 写道
mali0330 写道
我就想知道你是如何看到的JVM的源代码,可以和je分享一下么?谢谢


JDK 工具包里面都有一个src文件,里面是source code,但native方法,与虚拟机相关的部分没有公开。

你知道怎么看Object中的clone方法的vative代码吗?我很想看,一直找不到在哪。。。。。。。。
0 请登录后投票
   发表时间:2010-01-14  
楼上的大大要看这个?
JVM_ENTRY(jobject, JVM_Clone(JNIEnv* env, jobject handle))
  JVMWrapper("JVM_Clone");
  Handle obj(THREAD, JNIHandles::resolve_non_null(handle));
  const KlassHandle klass (THREAD, obj->klass());
  JvmtiVMObjectAllocEventCollector oam;

#ifdef ASSERT
  // Just checking that the cloneable flag is set correct
  if (obj->is_javaArray()) {
    guarantee(klass->is_cloneable(), "all arrays are cloneable");
  } else {
    guarantee(obj->is_instance(), "should be instanceOop");
    bool cloneable = klass->is_subtype_of(SystemDictionary::cloneable_klass());
    guarantee(cloneable == klass->is_cloneable(), "incorrect cloneable flag");
  }
#endif

  // Check if class of obj supports the Cloneable interface.
  // All arrays are considered to be cloneable (See JLS 20.1.5)
  if (!klass->is_cloneable()) {
    ResourceMark rm(THREAD);
    THROW_MSG_0(vmSymbols::java_lang_CloneNotSupportedException(), klass->external_name());
  }

  // Make shallow object copy
  const int size = obj->size();
  oop new_obj = NULL;
  if (obj->is_javaArray()) {
    const int length = ((arrayOop)obj())->length();
    new_obj = CollectedHeap::array_allocate(klass, size, length, CHECK_NULL);
  } else {
    new_obj = CollectedHeap::obj_allocate(klass, size, CHECK_NULL);
  }
  // 4839641 (4840070): We must do an oop-atomic copy, because if another thread
  // is modifying a reference field in the clonee, a non-oop-atomic copy might
  // be suspended in the middle of copying the pointer and end up with parts
  // of two different pointers in the field.  Subsequent dereferences will crash.
  // 4846409: an oop-copy of objects with long or double fields or arrays of same
  // won't copy the longs/doubles atomically in 32-bit vm's, so we copy jlongs instead
  // of oops.  We know objects are aligned on a minimum of an jlong boundary.
  // The same is true of StubRoutines::object_copy and the various oop_copy
  // variants, and of the code generated by the inline_native_clone intrinsic.
  assert(MinObjAlignmentInBytes >= BytesPerLong, "objects misaligned");
  Copy::conjoint_jlongs_atomic((jlong*)obj(), (jlong*)new_obj,
                               (size_t)align_object_size(size) / HeapWordsPerLong);
  // Clear the header
  new_obj->init_mark();

  // Store check (mark entire object and let gc sort it out)
  BarrierSet* bs = Universe::heap()->barrier_set();
  assert(bs->has_write_region_opt(), "Barrier set does not have write_region");
  bs->write_region(MemRegion((HeapWord*)new_obj, size));

  // Caution: this involves a java upcall, so the clone should be
  // "gc-robust" by this stage.
  if (klass->has_finalizer()) {
    assert(obj->is_instance(), "should be instanceOop");
    new_obj = instanceKlass::register_finalizer(instanceOop(new_obj), CHECK_NULL);
  }

  return JNIHandles::make_local(env, oop(new_obj));
JVM_END
0 请登录后投票
   发表时间:2010-01-19  
prowl 写道
msnvip 写道
public class TestFan {

	/**
	 * @param args
	 * 
	 * User是一个空class
	 */
	public static void main(String[] args) {
		int i = 0;
		test(null);
	}

	//
	//不添加此方法.编译,运行没问题.输出显示调用的user
	//添加此方法时候.编译期出错The method test(String) is ambiguous for the type TestFan
	public static void test(String str)
	{
		System.out.println("string");
	}
	
	
	public static void test(User users)
	{
		System.out.println("user");
	}
	
	public static void test(Object users)
	{
		System.out.println("object");
	}
}


请教下:
1.没添加那个方法时候.为什么调用的会是user的那个方法?
2.添加后为什么出错了



我觉得这可能是编译器的默认行为吧 默认
Object , ? extends Object 


类似多态?

2个子类,编译器识别不了了。。。

public class Test {
	class A {
	}

	class B extends A {
	}

	public static void main(String[] args) {
		test(null);
	}

	public static void test(A a) {
		System.out.println("A");
	}

	public static void test(B b) {
		System.out.println("B");
	}
}

结果,编译通过,输出B。

public class Test {
	class A {
	}

	class B {
	}

	public static void main(String[] args) {
		test((B) null);
	}

	public static void test(A a) {
		System.out.println("A");
	}

	public static void test(B b) {
		System.out.println("B");
	}
}

类A与B没有继承关系时,须将null强制转换。

因此,如果有继承关系的方法重载,会尽可能调用子类那个方法。
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics