十六、集合
(一)集合和数组的对比:
集合可以自动扩容,数组长度固定。
集合可以存储引用数据类型不能直接存基本数据类型,数组都可以存储。
注:若集合要存储基本数据类型(byte,short,char,int......)则需要使用对应的包装类来代替
(二)集合对象构造方法:
格式:
ArrayList<泛型> list = new ArrayList<泛型>(); //泛型:限定集合中存储数据的类型
ArrayList<泛型> list = new ArrayList<>();
例子:
ArrayList<String> list = new ArrayList<>(); System.out.println(list); //输出结果为 [] //ArrayList打印的对象不是地址值,是集合中存储数据内容,并且在打印时会用[ ]将所有数据进行包裹
(三)集合成员方法(增删改查)
例:
ArrayList<String> list = new ArrayList<>(); list.add("abc"); list.add("def"); list.add("ghi"); System.out.println(list.add("jkl")); //输出为:true add方法返回的是boolean类型的变量,无论添加什么元素都是返回true System.out.println(list); //[abc, def, ghi, jkl] System.out.println(list.remove("abc")); //输出为:true remove方法返回的是boolean类型的变量 System.out.println(list.remove("fff")); //输出为:false 括号内数据不存在于集合中就会返回false System.out.println(list); //输出为:[def, ghi, jkl] System.out.println(list.remove(2)); //输出为:jkl 删除集合中索引为2的元素并且返回这个元素的值 System.out.println(list); //输出为: [def, ghi] System.out.println(list.set(1,"fuck")); //输出为:ghi 修改集合中对应索引的元素值,并且将原来的元素值返回 System.out.println(list); //输出为:[def, fuck] System.out.println(list.get(1)); //输出为:fuck 根据索引返回集合中对应的元素值 System.out.println(list.size()); //输出为:2 返回集合的长度
十七、Static
静态变量:
用static来修饰类中的成员变量,称为静态变量:
特点:该类被所有对象共享,不属于对象而是属于类,随着类的加载而加载,优先于对象。
调用方式:类名调用(推荐)/ 对象名调用
public class Student {
private String name;
private String gender;
private int age;
public static String teachername; //用static修饰
public Student(){
}
public Student(String name,int age,String gender){
this.name=name;
this.age=age;
this.gender=gender;
}
}
内存中静态变量的出现是优先于对象的,静态变量是类的属性而不是创建的对象的属性(随着类的加载而出现,优先于对象):
随后代码运行到new一个Student对象s1部分,在堆内存中开辟一个空间,将地址赋值给s1,地址指向的空间中是对象的初始值,若要调用这个Student类的静态变量teachername,则会访问静态存储位置:
随后通过s1的地址值,在运行到赋值代码时,通过指针修改地址对应的空间中的值name与age,打印数据时先调用成员方法show,再访问s1地址中的name与age,最后去访问静态存储位置的teachername:
创建新对象s2同理,开辟空间存储默认值,若后续调用teachername则需要去静态存储位置访问:
静态方法:
被static修饰的成员方法,称为静态方法
特点:多用在测试类和工具类中 JavaBean类中很少用
调用方式:如果是本类中调用,则可以直接方法名调用。如果是调用其他类,则用类名调用或者对象名调用。
例:工具类ArrayUtill中的静态方法printArr
工具类:帮助我们做一些事情但是不描述任何事物的类
特点:①类名见名知意 ②私有化构建方法 ③方法定义为静态
例:
静态方法注意事项:
①静态方法只能访问静态变量和静态方法
②非静态方法可以访问静态变量或者静态方法,也可以访问非静态的成员变量和非静态的成员方法
③静态方法中是没有this关键词
重新认识main方法:
import java.util.ArrayList;
public class TestDemo {
public static void main(String[] args) {
}
}
public:被JVM(虚拟机)调用,访问权限足够大
static:被JVM调用,不用创建对象,直接类名访问。因为main方法是静态的,所以测试类中其他 方法也必须是静态的。
void:被JVM调用,不需要给JVM返回值。
mian:一个通用的名称,虽然不是关键字,但是被JVM识别(主程序入口)。
String[] args:以前用于接受键盘录入数据的,现在没有用。
十八、继承
封装的不同类里面很多属性重复:
为这些重复的属性创建一个单独的地方存放(第三个类)成为父类:
格式:
Java中提供了一个关键字extends,用这个关键字,可以让一个类和另一个类建立起继承关系。
public class 子类 extends 父类 { }
例: public class Student extends Person { }
Student称为子类(派生类) Person称为父类(基类或超类)
继承的好处:
①可以把多个子类重复的代码抽取到父类中,提高代码复用性
②子类可以在父类的基础上,增加其他的功能,使其更功能强大。
当类和类之间,存在相同(共性)的内容,并满足子类是父类的一种,就可以考虑使用继承,来优化代码。
继承的特点:
Java只支持单继承,不支持多继承,但支持多层继承。
单继承:
一个类只能继承一个直接父类
多层继承:
子类A继承父类B,父类B可以继承父类C
C是A的间接父类,B是A的直接父类
每一个类都直接或间接的继承与Object类
子类只能访问父类中非私有的成员:
成员方法:
在满足非private修饰的前提下,子类能够继承父类中的方法。
而如果方法满足虚方法的前提,则子类在调用方法时不需要逐层返回父类去查询方法。
系统会生成一个虚方法表,每次继承都会继承父类的虚方法表,当子类调用的方法是虚方法时,可以直接在表中查询,但是如果调用的方法不是虚方法,则会逐层返回父类查询。
继承中成员变量的访问特点:
就近原则(先在局部内找,再从本类成员位置找,再从父类找,逐级向上。)
例: 子类中有name,父类也有 输出为子类name
public class animal {
String name="动物";
}
public class Dog extends animal{
String name="狗";
public void watchhouse(){
System.out.println("看家");
}
public void printname(){
System.out.println(name);
}
}
import java.util.ArrayList;
public class TestDemo {
public static void main(String[] args) {
Hashiqi dog1=new Hashiqi();
dog1.printname(); //狗
}
}
子类中没有,父类中有,输出为父类。
若都没有则会报错。
同时还可以用 this 和 super 关键字来解决变量重名
this(直接从本类成员开始逐级向上找)
super(直接从父类成员开始逐级向上找)
例:
public class Dog extends animal{
String name="狗";
public void watchhouse(){
System.out.println("看家");
}
public void printname(){
String name="狗狗狗";
System.out.println(name); //狗狗狗
System.out.println(this.name); //狗
System.out.println(super.name); //动物
}
}
成员方法的调用同理
public class animal {
String name="动物";
public void eat(){
System.out.println("吃饭");
}
public void drink(){
System.out.println("喝水");
}
}
public class Dog extends animal{
String name="狗";
public void watchhouse(){
System.out.println("看家");
}
public void eat(){
System.out.println("吃狗饭");
}
public void printeat(){
this.eat(); //吃狗饭
super.eat(); //吃饭
}
}
方法的重写:
当父类中的方法不能满足子类现在的需求时,需要进行方法重写。
要求:
1、重写方法的名称、形参列表必须与父类中一致。
2、子类重写方法时,访问权限子类必须大于父类(空着不写<protected<pulic)。
3、子类重写父类方法时,返回值类型必须小于等于父类。
4、建议:重写的方法尽量和父类一致
5、只有被添加到虚方法表中的方法才能被重写。
书写格式:
在继承体系中,子类出现了和父类一样的方法声明,就称子类这个方法是重写的方法。
@Override重写注解
1、@Override是放在重写后的方法上,校验子类重写时语法是否正确。
2、加上注解后如果有红色波浪线,表示语法错误。
建议重写方法都加上@Override注解
例:
@Override
public void eat(){
System.out.println("吃狗饭");
}
方法重写的本质:
覆盖继承过来的虚方法表中对应的方法:
如下,B在继承父类C时,对方法2进行了重写,覆盖了继承时一并继承过来的虚方法表中的方法2.
A同样。
构造方法的访问特点:
1、父类中的构造方法不会被子类继承,但是可以通过super调用。
2、默认先访问父类的无参构造,再执行自己的。
(子类初始化前,一定会调用父类构造方法先完成父类数据空间的初始化)
子类构造方法的第一行语句默认为:super(),不写也存在,且必须在第一行。
3、如果子类想要调用父类有参构造,必须手动写super进行调用。
public class animal {
String name="动物";
public animal(){
System.out.println("动物类的无参构造");
}
}
public class Dog extends animal{
String name="狗";
public Dog(){
//super();默认存在的代码,就算不写系统也会自动添加,且一定在第一行
System.out.println("狗的无参构造");
}
}
import java.util.ArrayList;
public class TestDemo {
public static void main(String[] args) {
Dog dog=new Dog();
}
}
输出为:动物的无参构造
狗的无参构造
父类的带参构造:
例:
public class animal {
String name;
int age;
public animal(){
}
public animal(String name,int age){
this.age=age;
this.name=name;
}
}
public class Dog extends animal{
public Dog(){
}
public Dog(String name,int age){
super(name,age);
}
}
import java.util.ArrayList;
public class TestDemo {
public static void main(String[] args) {
Dog dog=new Dog("bage",20);
System.out.println(dog.name+","+dog.age); // 输出为: bage,20
}
}
this、super总结:
this:理解为一个变量,表示当前方法调用者的地址值;
super:代表父类存储空间。
this构造方法示例:
public class animal {
String name;
int age;
public animal(){
}
public animal(String name,int age){
this.age=age;
this.name=name;
}
}
public class Dog extends animal{
public Dog(){
this("狗",20); //访问本类中的构造方法
}
public Dog(String name,int age){
super(name,age);
}
}
import java.util.ArrayList;
public class TestDemo {
public static void main(String[] args) {
Dog dog=new Dog();
System.out.println(dog.name+","+dog.age);
}
}
输出结果为:狗,20