文章目录
前言
1.理解泛型的作用。
2.了解成员变量和成员方法
泛型
什么是泛型
List:这里的就是泛型标志,Map<K,V>这里<K,V>也是泛型标记。
泛型:就是类再定义时无法确认类中成员的类型(属性,方法),而是类再创建时指定具体的数据类型。
泛型的意义:泛型提高了代码的复用性和安全性,通过参数化类型,我们可以在类、接口和方法中操作多种数据类型,而无需针对每种类型编写重复的代码
为什么使用泛型
例子: 定义一个Point 点类,要求如下:
- 它的坐标值可以是整数。x=15,y=25
- 它的坐标值也可以都是小数: x=15.5 y=25.5
- 它的坐标值也可以都是字符串类型: x=“北纬15度” y=“东经258度”
public class Point {
private Object x;
private Object y;//因为Object是所有类的父类,而且多态,子类类型可以自动向父类类型转化。
public Point(Object x, Object y) {
this.x = x;
this.y = y;
}
@Override
public String toString() {
return "Point{" +
"x=" + x +
", y=" + y +
'}';
}
public Object getX() {
return x;
}
public void setX(Object x) {
this.x = x;
}
public Object getY() {
return y;
}
public void setY(Object y) {
this.y = y;
}
}
public class Point {
private Object x;
private Object y;//因为Object是所有类的父类,而且多态,子类类型可以自动向父类类型转化。
public Point(Object x, Object y) {
this.x = x;
this.y = y;
}
@Override
public String toString() {
return "Point{" +
"x=" + x +
", y=" + y +
'}';
}
public Object getX() {
return x;
}
public void setX(Object x) {
this.x = x;
}
public Object getY() {
return y;
}
public void setY(Object y) {
this.y = y;
}
}
如何使用泛型
泛型可以解决数据类型的安全性问题,其主要原理是在类声明时通过一个标识表示类中某个属性的数据类型或者是某个方法的返回值及参数类型。这样在类声明或者实例化时只要指定好需要的类型即可。
语法:
public class 类名<T,E,B>{
private T a;
public T getA(){}
public void setA(T t){}
}
使用泛型来解决Point类的安全问题
public class Point<T> {
private T x;
private T y;//因为Object是所有类的父类,而且多态,子类类型可以自动向父类类型转化。
public Point(T x, T y) {
this.x = x;
this.y = y;
}
@Override
public String toString() {
return "Point{" +
"x=" + x +
", y=" + y +
'}';
}
public T getX() {
return x;
}
public void setX(T x) {
this.x = x;
}
public T getY() {
return y;
}
public void setY(T y) {
this.y = y;
}
}
public class Test {
public static void main(String[] args) {
Point<Integer> p1=new Point<>(15,25);
Point<Double> p2=new Point<>(25.5,36.6);
Point<String> p3=new Point<>("东经150度","北纬36度");
String x = p3.getX();
Integer x1 = p1.getX();//不会出现数据类型安全问题。
// 注意: 泛型的类型必须指定为引用类型,不能使用基本类型【byte short int long float double boolean char】。--->包装类:Byte Short ...Integer .......Character
//我们我们在创建泛型类对象时没有指定泛型:--它就是Object类型
}
}
泛型通配符
在开发中对象的引用传递是最常见的,但是如果在泛型类的操作中,在进行引用传递时泛型类型必须匹配才可以传递,否则是无法传递的。
对象的引用传递和值传递。
public class Test {
public static void main(String[] args) {
Info<Integer> a=new Info<>(15);
Info<String> b=new Info<>("Hello");
fun(a);
fun(b);//泛型的引用传递,要求数据类型匹配而且泛型也要匹配。
}
//任意的泛型都可以传递过来。 使用泛型通配符。?
public static void fun(Info<?> info){
info.show();
}
}
class Info<T>{
private T var;
public Info(T var) {
this.var = var;
}
public void show(){
System.out.println("var==============="+var);
}
public T getVar() {
return var;
}
public void setVar(T var) {
this.var = var;
}
}
泛型的限制
在引用传递中,在泛型操作中也可以设置一个泛型对象的范围上限和范围下限。范围上限使用extends关键字声明,表示参数化的类型可能是所指定的类型或者是此类型的子类,而范围下限使用super进行声明,表示参数化的类型可能是所指定的类型或者此类型的父类型。
语法:
public void 方法名(Info<? extends Number> info){
//传递参数的泛型必须是Number或者Number的子类
}
public void 方法名(Info<? super Number> info){
//传递参数的泛型必须是Number或者Number的父类
}
public class Test{
public static void main(String[] args) {
Info<Integer> a=new Info<>(15);
Info<String> b=new Info<>("Hello");
Info<Number> c=new Info<>(25.5);
fun2(a);
// fun2(b);//泛型的引用传递,要求数据类型匹配而且泛型也要匹配。
fun2(c);
Info<Object> d=new Info<>(258);
fun3(c);
// fun3(a);
// fun3(b);
fun3(d);
}
//限定泛型的上线:泛型的限制使用在方法的引用传递中。
public static void fun2(Info<? extends Number> info){
info.show();
}
//限定泛型的下限
public static void fun3(Info<? super Number> info){
info.show();
}
//任意的泛型都可以传递过来。 使用泛型通配符。?
public static void fun(Info<?> info){
info.show();
}
}
class Info<T>{
private T var;
public Info(T var) {
this.var = var;
}
public void show(){
System.out.println("var==============="+var);
}
public T getVar() {
return var;
}
public void setVar(T var) {
this.var = var;
}
}
泛型接口
List ArrayList
在JDK1.5之后,不仅可以声明泛型类,也可以声明泛型接口,声明泛型接口和声明泛型类的语法类似,也是在接口名称后面加上, 格式如下:
[访问权限] interface 接口名称<泛型标识>{
}
泛型接口的实现类的方式有两种:
(1)在创建类时也声明泛型而且该泛型的标识必须和接口的标识一致。
(2)在类实现泛型接口时,指明该泛型的数据类型。
public class Test {
}
interface USB<T>{
public void show(T t);
}
//在创建类时,也指定泛型要求必须和接口的泛型标志一致
class Upan<T> implements USB<T>{
@Override
public void show(T t) {
}
}
class Shu implements USB<String>{
@Override
public void show(String s) {
}
}
泛型方法
前面学习的所有泛型操作都是将整个类进行泛型化,但同样也可以在类中定义泛型化的方法。泛型方法的定义与其所在的类是否是泛型类是没有任何关系的,所在的类可以是泛型类,也可以不是泛型类。
public class Test {
public static void main(String[] args) {
Test t=new Test();
String hello = t.fun("hello");
Integer fun = t.fun(15);
}
//泛型方法: <T>在方法的返回值前面多了个泛型标志
public <T> T fun(T t){
System.out.println("结果为:"+t);
return t;
}
}
- 泛型类: public class 类名<标志,标志…>{}
- 通配符: ?
- 限制泛型类型: ? super Number ? extends Number 引用传递
- 泛型接口: public interface 接口<标志,标志…>{}
- 泛型方法: public <标志> 返回值 方法名(参数列表){}
成员变量
成员变量:定义在类内部、方法外部的变量,用于描述对象的属性,它们可以是基本数据类型,也可以是对象类型。成员变量在对象创建时初始化,并在对象整个生命周期内存在。
如何定义成员变量
【修饰符】 class 类名{
【①修饰符】 数据类型 成员变量名;
}
【】表示可选
public class Person {
public static String star;//星球 成员变量,因为它有static修饰,它就是静态变量
public String name;//名称 成员变量,因为它没有static修饰,它就是非静态成员变量,简称实例变量
public String idCard;//身份证 成员变量,因为它没有static修饰,它就是非静态成员变量,简称实例变量
public String phone;//手机 成员变量,因为它没有static修饰,它就是非静态成员变量,简称实例变量
public String qq;//qq号 成员变量,因为它没有static修饰,它就是非静态成员变量,简称实例变量
}
成员变量的作用是描述事物的属性和数据特征。
如何使用成员变量
跨类使用成员变量:
对象名.实例变量
类名.静态变量
虽然静态变量也可以通过 “对象.静态变量”的方式访问,但是我们更推荐“类名.静态变量”
成员变量的特点
- 实例变量的值是每一个对象都是独立的
- 静态变量的值是整个类共享的,无论是哪个对象,或类修改了它,那么都是统一修改的,因为它只有1份。
- 成员变量有默认值
数据类型 | 默认值 |
---|---|
byte | 0 |
short | 0 |
int | 0 |
long | 0L |
float | 0.0F |
double | 0.0 |
char | \u0000 编码值为0的空字符 |
boolean | false |
引用数据类型 | null |
静态变量和实例变量对比
区别 | 实例变量 | 静态变量 |
---|---|---|
跨类访问方式 | 对象名.实例变量 | 类名.静态变量 |
它的值是共享的还是独立 | 每一个对象独立的 | 整个类共享的 |
是否有默认值 | 有 | 有 |
内存位置 | 堆 | 方法区 |
引用数据类型的成员变量
- 所有引用数据类型的成员变量,默认值是null
- 如果没有给引用数据类型的成员变量赋值对应的对象,那么通过它. 成员变量等都会发生 NullPointerException(空指针异常)
成员方法
成员方法:类中定义的用于执行操作或计算的函数。方法可以包含参数、返回值,并且可以访问类的成员变量(如果需要,还可以通过特定关键字访问其他对象的成员变量)方法是类实现其功能的关键部分。
方法的分类
根据方法的修饰符是否有static修饰,分为:
静态方法
- 本类调用:直接用
- 跨类调用:类名.静态方法
非静态方法(实例方法)
- 本类使用:直接使用
- 跨类调用:对象名.实例方法
成员方法使用本类的成员变量
总结:本类的静态方法,不能直接使用 本类的实例变量 或 实例方法。
访问方式 | 是否允许 |
---|---|
本类的静态方法 访问 本类的静态变量、静态方法 | 可以 |
本类的静态方法 访问 本类的实例变量、实例方法 | 不可以 |
本类的实例方法 访问 本类的实例变量、实例方法 | 可以 |
本类的实例方法 访问 本类的静态变量、静态方法 | 可以 |
总结
今天的学习让我对Java的泛型机制有了更深刻的理解,意识到它在提升代码质量、可维护性和可重用性方面的巨大作用。同时,复习成员变量和成员方法也巩固了我的面向对象编程基础,为后续更高级的Java特性和设计模式学习打下了坚实的基础。