内部类:
实例内部类
静态内部类
匿名内部类
本地内部类–》基本不会使用到在方法里定义的一个类。
实例内部类:
面试问题:1.如何拿到实例内部类的对象?
/*OuterClass 外部类
InnerClass内部类
外部类名.实例内部类类名 in=外部类对象的引用.new 内部类对象
**/
OuterClass outerClass=new OuterClass();
//访问实例内部类我们需要通过外部类的引用,包括类名去访问
OuterClass.InnerClass in=outerClass.new InnerClass();
2.在实例内部类当中,是否可以定义static的数据成员?
不能!是错误的
可以添加的是 static final在实例成员内部必须是在编译时期内就确定的(常量) 不能仅添加 static
3.内部类可以访问所有的外部类成员包括私有的。
4.实例内部类是否有额外的开销?
有额外开销,因为内部类中包含了外部类的 this
InnerClass是OuterClass 的 成员
OuterClass .this->拿到外部类名.this拿到外部类的引用。可以在内部类中访问到外部类的对象。因为用类名可以 . 证明是一个静态的。this从本质上说是静态的
一个class会生成一个class文件。java高效率,使用哪一个才会去加载。
内部类生成的字节码文件文件名是:OuterClass$InnerClass.class
静态内部类:
//此时我们拿到静态内部类的对象,被static修饰只需要通过类名获取即可
OuterClass2.InnerClass2 in=new OuterClass2.InnerClass2();
静态内部类-》static 顶级嵌套类
1.如何拿到静态内部类的实例对象?
外部类名 . 静态内部类名 in = new 外部类类名 . 内部类();
静态的内部类,访问外部的静态量。我们只需要使用OuterClass2.InnerClass2 .即可。
2.静态内部类能否访问外部类的成员?
可以直接访问到外部类的静态成员,不能直接访问实例成员但可以间接进行访问,
访问方法,我们在内部类中建一个带一个参数的构造方法
public InnerClass2 ( OuterClass2 out ){ }
然后在main函数中我们先获取外部类的对象。
OuterClass2 outerClass2=new OuterClass2();
获取到之后可以以传参的形式将外部类的引用传入到内部类中
OuterClass2.InnerClass2 in=new OuterClass2.InnerClass2(outerClass2);
此时我们去接收外部类传入的对象。
OuterClass2 o=null;定义一个接收值。
public InnerClass2(OuterClass2 out){
this.o=out;
};//现在o就是我们外部类的引用可以进行一个访问到外部类的
// 实例成员
匿名内部类:(线程)
class MyThread{
public void func(){
System.out.println("out::MyThread::func");
}
}
public class TestDemo1 {
public static void main(String[] args) {
//new MyThread();匿名对象
new MyThread(){
//这东西就是匿名内部类需要重写
@Override
public void func() {
super.func();//有继承关系可以看做是外部类MyThread的子类
}
}.func();
}
}
泛型:
1.实现一个通用的ArrayList
2.泛型:TestMyArrayList:他只是一个占位符
证明当前的类是一个泛型类
3.泛型的坑:泛型不能被new 坑2 :泛型的参数必须是引用类型不能是简单类型。
4.泛型的意义
1.可以进行自动类型检查
2.可以自动进行类型转换
5.泛型到底是怎么被编译的?
最重要的 类型的擦除机制-》object 并不是替换
只是将等进行擦除为object 也就是将
@SuppressWarnings(“unchecked”) 代表强制压制警告
6.泛型参数是不参与类型的组成的。
了解
类型形参一般使用一个大写字母表示,常用的名称有:
E 表示 Element
K 表示 Key
V 表示 Value
N 表示 Number
T 表示 Type
S, U, V 等等 - 第二、第三、第四个类型
public class TestMyArrayList<T> {
public T []elem;
public int usedSize;
public TestMyArrayList(){
//this.elem=new T[10] 错误的
this.elem=(T[])new Object[10];//泛型不能被new,我们进行强转
this.usedSize=0;
}
public void add(T data){
this.elem[this.usedSize]=data;
this.usedSize++;
}
public T get(){
T a=this.elem[this.usedSize-1];
this.usedSize--;
return a ;
}
}
测试代码:
public class TestMain {
public static void main(String[] args) {
TestMyArrayList<Integer> tA=new TestMyArrayList<>();
tA.add(10);
double ret=tA.get();//报错原因 没有类型转换
TestMyArrayList<String> tA1=new TestMyArrayList<>();
tA1.add("zhangsan");
}
}
类型擦除:
package com.bit.src;
import java.util.ArrayList;
//这里的extends就是我们泛型的上界 就是我们传入的T一定是需要实现了Comparable接口的
//写一个这样的类相当于是一个万能的类 我们只需要在main函数中定义它的类型即可
//当我们只有整形数字之间我们的使用><来比较 如果类型不确定 我们是需要将T类型本来是往
// Object的方面擦除 我们手动引导至compareTo 进行实现比较
class Algorithm<T extends Comparable<T>> {//T extends Number 呢我们只能传入的是数字类型的比如Integer
//double等
public T MaxNum(T[]array){
T max=array[0];
for (int i = 1; i < array.length ; i++) {
if (array[i].compareTo(max)>0){//此时因为我们是一个T类型的数组 不能直接使用>号进行比较
//使用Compare To
max=array[i];
}
}
return max;
}
}
class Algorithm2 {//我们现在需要的是不需要通过对象的引用进行访问。 我们需要添加static
public static<T extends Comparable<T>> T MaxNum(T[]array){
T max=array[0];
for (int i = 1; i < array.length ; i++) {
if (array[i].compareTo(max)>0){//此时因为我们是一个T类型的数组 不能直接使用>号进行比较
//使用Compare To
max=array[i];
}
}
return max;
}
}
class Algorithm3{
public static <T> void print(ArrayList<T> array){
for (int i = 0; i <array.size() ; i++) {
System.out.print(array.get(i));
}
}
//指定就是我们的通配符
public static void print2(ArrayList<?> array){
//Object说明该类型的基类就是Object
for (Object obj: array) {
System.out.print(obj+" ");
}
System.out.println();
}
}
/*泛型:指定
通配符:代表 只读的
* */
public class TestDemo {
public static void main(String[] args) {
ArrayList<Double> array=new ArrayList<>();
array.add(1.0 );
array.add(2.0);
array.add(3.0);
Algorithm3.print2(array);
}
public static void main2(String[] args) {
//Integer[]array={1,3,5,7,9}; 会有一个推演的过程
String[]array1={"abc","def","ghk"};
String a=Algorithm2.MaxNum(array1);//这里我们没有去指定一个 这样直接进行引用的话
//我们会自动先去检测你数组中的内容
System.out.println(a);
}
public static void main1(String[] args) {
Algorithm<Integer> algorithm=new Algorithm<>();
Integer[]array={1,3,5,7,9};//在这里我们需要使用包装类进行定义我们的数组
Integer a=algorithm.MaxNum(array);//接收类型就是T类型 我们目前所定义的即为Integer
System.out.println(a);
Algorithm<String> algorithm1=new Algorithm<>();
String[]array1={"abc","def","ghk"};
String str=algorithm1.MaxNum(array1);
System.out.println(str);
}
}
在平常来说我们Object 使我们所有类的父类 但是只要一牵扯到泛型
我们泛型是有一个擦除机制,在编译过程中会将所有类擦除为Object 所有泛型中不会有父子类型关系
我们需要使用通配符来确定父子关系
泛型只有上界。
在通配符中是有上下界的:
<?extends number> 这种来说上界就是number 我们的类型只能选择数字类型