获取子类穿过来的泛型

 
public abstract class BaseDaoImpl<T> implements BaseDao<T> {

	protected Class<T> clazz;

	public BaseDaoImpl() {
		ParameterizedType pt = (ParameterizedType) this.getClass().getGenericSuperclass();
		clazz = (Class) pt.getActualTypeArguments()[0];

		System.out.println("---> clazz = " + clazz);
	}

	public void save(T entity) {
		getSession().save(entity);
	}

	public void delete(Long id) {
		Object obj = getSession().get(clazz, id);
		getSession().delete(obj);
	}

<think>好的,我现在需要解释Java中关于子类继承父类的概念。用户可能对的基础有一定了解,但需要更深入的理解子类如何继承父类的。首先,我得回忆一下Java的基本机制,特别是继承时的类参数处理。 首先,父类如果是类,子类在继承时可以选择保留父类的参数,或者具体化父类的类参数。例如,父类可能是class Parent<T>,子类可以是class Child<T> extends Parent<T>,这样Child也成了类,保留了父类的。或者,子类可能指定具体的类,如class Child extends Parent<String>,此时父类的T被确定为String,子类不需要再声明参数。 接下来需要考虑类擦除的问题。Java的在编译后会被擦除,所以运行时无法获取参数的具体信息。这可能会影响子类继承时的行为,比如方法重写和类检查。 然后,用户可能需要了解子类如何添加自己的参数。例如,子类可以同时拥有自己的和继承父类的,如class Child<S, T> extends Parent<T>,这样父类使用T,而子类引入新的S。这种情况下,实例化子类时需要指定两个类参数。 另外,方法的继承也需要考虑。子类可以重写父类的方法,但必须保持类参数的兼容性。如果父类的方法使用了子类在重写时可以使用相同或更具体的类,但需要注意类擦除可能导致的问题,比如方法签名冲突。 还需要讨论通配符和边界的问题。父类可能使用了extends或super通配符,子类在继承时如何处理这些情况。例如,如果父类有<? extends Number>,子类可能需要适配这个边界,或者进一步限制类参数。 可能的误区包括误以为子类继承父类时会自动实例化类参数,或者混淆了类继承和方法的重写。需要指出子类必须显式处理父类的类参数,否则可能导致编译错误。 最后,应该通过示例代码来具体说明不同情况下的用法,比如保留父类、具体化类参数、子类添加新参数等。这些例子可以帮助用户更直观地理解概念。 总结一下,我需要分步骤解释子类继承父类的不同情况,强调类参数的处理方式,类擦除的影响,以及可能的错误用法。同时,提供清晰的代码示例来辅助说明,确保用户能够逐步理解这一机制。</think>在Java中,子类继承父类时,参数的处理需要特别注意。以下是分步说明: --- ### 1. **基础继承:保留父类** 子类可以继续使用父类的参数,此时子类自身也需声明为类。 ```java class Parent<T> { T data; void setData(T data) { this.data = data; } } // 子类保留父类参数 class Child<T> extends Parent<T> { void print() { System.out.println(data); } } ``` - **使用示例**: ```java Child<String> child = new Child<>(); child.setData("Hello"); // 类安全 ``` --- ### 2. **具体化父类** 子类可以直接为父类指定具体类参数,此时子类不再是类。 ```java class Child extends Parent<String> { void print() { System.out.println(data.toUpperCase()); } } ``` - **使用示例**: ```java Child child = new Child(); child.setData("world"); // 父类T已被固定为String ``` --- ### 3. **子类添加新参数** 子类可以同时保留父类并引入自己的参数。 ```java class Child<S, T> extends Parent<T> { S metadata; void setMetadata(S metadata) { this.metadata = metadata; } } ``` - **使用示例**: ```java Child<Integer, String> child = new Child<>(); child.setData("Java"); child.setMetadata(100); // S=Integer, T=String ``` --- ### 4. **边界与继承** 若父类定义了边界,子类必须遵守或更严格。 ```java class Parent<T extends Number> { /* ... */ } // 合法:子类沿用父类边界 class Child1<T extends Number> extends Parent<T> {} // 合法:子类缩小边界 class Child2<T extends Integer> extends Parent<T> {} ``` --- ### 5. **类擦除的影响** 由于类擦除,以下代码会编译错误: ```java class Parent<T> { void setData(T data) { /* ... */ } } // 错误!重写方法因类擦除导致签名冲突 class Child extends Parent<String> { void setData(String data) { /* ... */ } // 实际编译后:setData(Object) // 与父类方法签名重复 } ``` **正确做法**:子类无需显式重写`setData`,直接继承即可。 --- ### 6. **方法的继承与重写** 子类可以重写父类的方法,但需保持兼容性: ```java class Parent { <T> void process(T data) { /* ... */ } } class Child extends Parent { @Override <T> void process(T data) { /* ... */ } // 合法重写 } ``` --- ### 关键点总结 1. **保留**:子类声明相同的参数(如`Child<T>`),延续父类的灵活性。 2. **指定具体类**:子类直接固定父类(如`Child extends Parent<String>`)。 3. **边界**:子类参数必须满足父类定义的类边界。 4. **类擦除陷阱**:避免因擦除导致方法签名冲突。 通过合理设计继承,可以实现类安全的代码复用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值