内部类
在类当中的叫做内部类而独立的类叫做外部类
静态内部类
用static修饰的内部类。
最常用,可以用权限修饰符设置访问权限,在本类中可以直接使用,在外部首先要权限允许,然后类似EasyB.InnerA a=new EasyB.InnerA()使用;
public class EasyA{
static class InnerA{ }
}
成员内部类
未使用static修饰的内部类。
必须使用实例对象调用 new EasyB().new InnerB();
public class EasyB{
class InnerB{ }
}
局部内部类
在方法中定义的一个类
public void inner() {
//修饰符都不行,因为只能在本方法使用
//static也不行,它是局部的
class InnerC{}
new InnerC();
}
匿名内部类
匿名内部类是一种在 Java 编程中创建临时的、无需命名的类的机制。
抽象类和接口都可以由匿名内部类实现:
//匿名内部类对象 接口也可以
AbstractClass ac=new AbstractClass() {
@Override
public void method() {}
};
AbstractClass acd=new AbstractClass() {
@Override
public void method() {}
};
//面试题:这两个类是不是同一种类?不是
Lambda表达式
仅支持函数式接口的实现,多行需要{}区分方法体
对于interface EasyInter{void method();}
EasyInter eil=()->{System.out.println("aaaaaaa");};
eil.method();
用EasyB的fun方法代替EasyInter为重写方法
EasyInter eii=EasyB::fun;
对于interface EasyInterA{int method();}
EasyInterA eila=()->12;//甚至如此,12代表返回值
代码块运行顺序
先有类再有对象
面试题
父类静态代码块->子类静态代码块->父类成员代码块->父类构造方法->子类成员代码块->子类构造方法
静态代码块
一个类的静态代码块只会执行一次
//加载类对象时执行
static{
System.out.println("子类静态代码块");
}
成员代码块
每一次new对象时执行
{
System.out.println("子类成员代码块");
}
容器
引言:数组只能存指定类型,长度是不可改变的,所以创建了List Set Map
List是一个接口,实现类有ArraList、LinkedList和Vector。
ArrayList
List list=new ArrayList();
创建后初始容量为0
底层Object数组 存储任意类型
ArrayList扩容方式:
默认初始容量10,也可以通过构造方法传入一个值设置初始容量
扩容1.5倍,如果不够则扩充最小满足值
最大容量Integer.MAX_VALUE-8安全容量,再大也只能是Integer.MAX_VALUE
常用方法
//添加
list.add("a");
list.add(12);
list.add(null);
list.add(33.33);
//获取元素
Object obj=list.get(0);
System.out.println(obj);
//在指定位置插入元素
list.add(1,44);
System.out.println(list);
list.add(list.size(),4);//可以,大于list.size()会报数组越界异常
//打印List
System.out.println(list);
//list.add(list.size()+1,5);//java.lang.IndexOutOfBoundsException
//设置元素
list.set(0, "b");
System.out.println(list);
//是否包含元素
System.out.println(list.contains("b"));
//是否包含另一个集合的所有元素
List listA=new ArrayList();
listA.add(33.33);
listA.add(null);
System.out.println(list.containsAll(listA));
//添加另一个集合的所有元素
list.addAll(listA);
//!=list.add(listA);把listA作为对象添加
//删除元素
list.remove("a");//删除第一个符合要求的元素,返回boolean
list.remove(0);//删除第一个元素,返回Object,下标越界报异常
//笔试题
//list.remove(44);//就近原则,当作删除下标44的元素
list.remove((Integer)44);//这样就可以删除了
list.removeAll(listA);//删除所有集合list和集合listA交集的元素
Iterator it=list.iterator();//获取一个迭代器,每个集合都有
while(it.hasNext()) {
//获取下一个对象并打印
System.out.println(it.next());
}
LinkedList
链表和ArrayList使用方法一样,存储数据的方式(结构)不一样 双向链表
使用链表存储理论上无限扩容,但由于下标为int类型的原因,实际上最大值Integer.MAX_VALUE
面试题:
ArrayList 和LinkedList性能比较
ArrayList是通过数组存储数据的 查找数据非常快
LinkedList查找速度慢,但通过双向检索优化检索速度,传入下标后和(size>>1)比较,选择从前往后函数从后往前
LinkedList是双向链表,同时记录前一个元素和后一个元素,实现双向检索所以删除插入操作性能更快
ArrayList插入和删除慢,需要后移
LinkedList插入和删除快,插入和删除只需要改变前后指向
扩展:for(Object item:arr){}
如果对item直接赋值,arr结构和内容不会改变,
但如果对item指向的对象的某一个成员对象修改,则集合arr中对应对象的成员对象也会改变