声明:该专栏本人重新过一遍java知识点时候的笔记汇总,主要是每天的知识点+题解,算是让自己巩固复习,也希望能给初学的朋友们一点帮助,大佬们不喜勿喷(抱拳了老铁!)
往期回顾:
Java学习day12:static关键字,字符串声明,字符串常量池-CSDN博客
Java学习day11:异常-CSDN博客
Java学习day10:多态、向下转型、instanceof关键字-CSDN博客
......
泛型:广泛的类型
因为在开发中对数据的一致性要求非常高
数组中存的数据 类型都是一致的。
但是数组有一个不好的地方,数组预先定义容量!!!
public class Demo1 {
public static void main(String[] args) {
//声明一个int类型数组
int[] arr = {1, 2, 3, 4};
char[] chs = {'a', 'b', 'c'};
//在数组的容量中 数据类型的都是一致的,很好!!!
//数组中的存储的数据确实一致的,但是开发不用!!!为啥?
//咱们 使用的时候,容量先定好的,而且数组添加数据删除数据,太麻烦了
}
}
因此实际开发中使用的是集合
这里我们简单补一下集合的知识点
1.数组长度固定,集合长度可变,最开始为1,自动扩容 |
2.数组能存基本数据类型和引用数据类型,集合能存引用数据类型,如果要存基本数据类型需要用包装类 |
ArrayList
boolean result=list.add("aaa"); | //其实是一定可以添加进去的,所以返回值都是true |
boolean result=list.remove("aaa"); String str=list.remove(0); |
//返回值表示是否修改成功 //删除list集合中索引为0的,返回值就是删除的内容 |
String str1=list.set(1,"mmm"); | //修改list集合中索引为1的内容为mmm,返回值就是被覆盖之前的内容 |
String str2=list.get(2); | //长度不再是length而是size方法 |
但是我们发现,集合里什么数据类型都可以存,好不好呢?
并不好,我们前面说了,需要保证数据的一致性。
public class Demo1 {
public static void main(String[] args) {
//实际开发中咱们需要后面即将学的集合
//集合就是用来存储的数据的!!!
ArrayList list = new ArrayList();//就把他当成一个容器即可
list.add("狗蛋");
list.add(250);
list.add('a');
list.add(false);
//啥类型的数据都可以存进来的
System.out.println(list);
//以上存储的数据好不好? 一点也不好!!!
//因为我们对数据类型一致性要求是比较高的!!!
//现在一个集合里什么数据都有,非常不好
//取值,每次都需要强转 太不好了
String str = (String)list.get(0);
System.out.println(str);
}
}
因此,基于以上种种,我们引出泛型这一知识点。
import java.util.ArrayList;
public class Demo1 {
public static void main(String[] args) {
//可以使用泛型 进行约束
ArrayList list1 = new ArrayList<>();
//告知编译器 这个集合只能存String类型的数据
list1.add("狗蛋");
list1.add("老邢");
list1.add("骚磊");
System.out.println(list1);
//取值
String s = list1.get(0);
System.out.println(s);
//ArrayList人家底层是封装了好了泛型,人家已经做好的
//学习自己如何自己写带有泛型的类 泛型的方法 等
}
}
成员方法:
public 返回值类型 方法名字 (参数列表) {
}带泛型:
public <无意义的占位符> 返回值类型 方法的名字 (参数列表) {
}
这里无意义的占位符: 可以是T 或者E 也可以是? 等 都可以。我们一般用T
这个时候其实就是方法的重载
public class Demo2 {
public static void main(String[] args) {
test(34);
test("狗");
test('蛋');
}
public static void test(int a) {
System.out.println(a);
}
public static void test(String a) {
System.out.println(a);
}
public static void test(char a) {
System.out.println(a);
}
}
改进后具有广泛性和普适性,但是其实就是方法的重载的升级版本。
public class Demo2 {
public static void main(String[] args) {
test(34);
test("狗");
test('蛋');
}
//使用泛型的写法
//这个T只是一个占位而已,如果你传了字符串 那么这个T就是String
//如果你传了一个整数 那么T 就是Integer
public static void test (T t) {
System.out.println(t);
}
//无返回值 无参的方法,没有必要使用泛型 没有意义
public static void test1 () {
T t = null;
//你这个结果和泛型有有啥关联?没有任何意义
System.out.println("嘻嘻哒");
}
//无返回值有参数的
public static void test (T t) {
System.out.println(t);
}
//无参 有返回值的方法,有咩有必要使用泛型? 没有
public static T test2() {
return null;
}
//有参 有返回值的方法,这个使用泛型有没有意义? 有!!!
public static T test3 (T t) {
return t;
}
//总结:
/**
* 泛型的方法一定是带有参数的才有意义!!!
* 无参的都是无意义的,而且一定要注意带有返回值的
* 这个返回值是和参数的T 数据类型要保持一致的
*/
class 类<无意义的占位符> {
}
//在声明对象的时候,指定好了咱们的T是啥数据类型
//那么 你的成员变量 T name 的T就是那种数据类型
但是我们知道,一个类里的成员变量的数据肯定不会是一样的,所以对于成员变量最好是不用,主要是看成员方法
(1)带有泛型的方法,最起码得有参数
想要一个方法中的泛型和类保持一致,一定在方法不要加
public void test1 (T t) {
System.out.println(t);
}
(2)如果在一个带有泛型的类,成员方法加
此时写的时候最好都不用T,直接用E,跟类的泛型类型区分开
public
void test (T t) {
System.out.println(t);
}
(3)如果是静态方法呢?对象创建的时候才 确定E数据类型,静态的方法在创建对象之前
这个E和上面 类的T无关的 自娱自乐
public static
void test2 (E e) {
System.out.println(e);
}
我们把三点注意事项汇总一下:
class Person {
// T name;//所以成员变量最好不用
// T age;
// T sex;
//主要看成员方法
//带有泛型的方法,最起码得有参数
//注意: 如果再一个带有泛型的类,成员方法不要加 了
public void test (T t) {
System.out.println(t);
}
//想要一个方法中的泛型和类保持一致,一定在方法不要加
public void test1 (T t) {
System.out.println(t);
}
//如果是静态方法呢?
//对象创建的时候才 确定E数据类型,静态的方法在创建对象之前
//这个E和上面 类的T无关的 自娱自乐
public static void test2 (E e) {
System.out.println(e);
}
}
public class Demo4 {
public static void main(String[] args) {
//在声明对象的时候,指定好了咱们的T是啥数据类型
//那么 你的成员变量 T name T 就是那种数据类型
Person stringPerson = new Person<>();
// stringPerson.name = "goudan";
// stringPerson 泛型 是String 就意味着test(T t)
//T 也应该是String
stringPerson.test(89);
stringPerson.test1("wuw");
Person person1 = new Person<>();
//person1.name = 98;
person1.test1(56);
//调用静态方法
Person.test2("hjsj");
}
}
再次强调:
在泛型类中如果写泛型方法的时候,不需要加
此时方法和类的泛型保持一致,如果加上
abstract class 类名<无意义的占位符> {
}
抽象类,暂时没有办法直接实例化,只能再写一个普通类去继承抽象类
继承了带有泛型的抽象类,那么继承类也需要有泛型!!!
abstract class A {
abstract void testA (T t);
}
class TestA extends A {
@Override
void testA(T t) {
System.out.println(t);
}
}
public class Demo1 {
public static void main(String[] args) {
//是int的包装类 就是代表的是int类型的数据
TestA testA = new TestA<>();
testA.testA(89);
}
}
补充介绍
int 的包装类 | Integer |
byte 的包装类 Byte | |
short 的包装类 | Short |
long 的包装类 | Long |
float 的包装类 | Float |
double 的包装类 | Double |
char 的包装类 | Character |
boolean 的包装类 | Boolean |
八大基本数据类型的包装类,要熟悉,其实有变化的就是int和char类型,其他都是首字母大写
interface 接口的名字<无意义的占位> {
}
//element 元素 Type 类型
interface B {
//成员方法
void eat(T t);
}
class TestB implements B {
@Override
public void eat(T t) {
System.out.println(t);
}
}
public class Demo2 {
public static void main(String[] args) {
TestB testB = new TestB<>();
testB.eat('g');
}
}
跟抽象类的继承很像,实现接口,调用实现类的方法
泛型方法:
publicvoid test (T t) {}
泛型类中的泛型方法,不要这个
public void test (T t) {}
泛型类:
class Person{ }
抽象类:
abstract class Person{ }
接口:
interface Person{ }
以上,就是今天的所有知识点了。泛型这个知识点是很简单的,大家静下心慢慢看,慢慢理解,不是什么大问题。
加油吧,预祝大家变得更强!