【笔记】Java- L2

内部类

image

  • 一个类对应提供的内容仅仅是为某一个类单独服务
  • 可以直接访问外部类的私有的成员变量

普通内部类

  • 直接将一个类的定义放在另外一个类的类体中
格式

访问修饰符 class 外部类的类名 {
访问修饰符 class 内部类的类名 {
内部类的类体;
}
}

调用方法

外部类名 外部类实例名 = new 外部类名();

注意内部类和外部类及内部方法有同一个成员变量时,用就近原则方法参数,非要用外部类或内部类的成员,外部类则用:外部类.this.成员名,内部类:this.成员名

外部类名.内部类名 内部类实例名 = 外部类实例名.new 内部类名();

静态内部类

  • 使用static修饰的内部类,属于类层级。
格式

访问修饰符 class 外部类的类名 {
访问修饰符 static class 内部类的类名 {
内部类的类体;
}
}

调用方式

外部类名.内部类名 内部类实例名 = new 外部类名.内部类名();

注意:warning:
  • 静态内部类 不能直接访问==外部类==的==非静态成员==
  • 静态内部类 可以==直接创建对象==
  • 如果静态内部类访问==外部类==中与本类内==同名的成员变量或方法==时,需要使用类名.的方式访问
  • 有static就是类层级,类名.调用
  • 没有static就是对象层级,引用.调用

局部内部类

  • 直接将一个类的定义放在方法体的内部
格式

访问修饰符 class 外部类的类名 {
访问修饰符 返回值类型 成员方法名(形参列表) {
class 内部类的类名 {
内部类的类体;
}
}
}

调用方式

方法内调用:

局部内部类类名 局部内部类实例名 = new 局部内部类类名();
局部内部类实例名.内部类方法名();

注意:warning:
  • 局部内部类只能在方法的内部可以使用
  • 局部内部类可以在方法体内部直接创建对应对象

匿名内部类:没听懂课程,无能为力

  • 就是指没有名字的内部类
    创建一个接口A,再创建一个实现接口的类B,再创建一个类C去调用,

String

  • string不是八大基本类型,是引用类型,声明变量是引用变量,是引用char基本类型的合集;
  • string可以用+连接,只要有一个string,则连接后都变成string
  • 空格: \t \f \r
  • equals 是比较两个字符串的内容是否相同,返回的是boolean值,相同就是true,不同就是false,不区分大小写
注意:warning:
  • 不能使用"=="运算符比较两个字符串是否相等

    • "=="只能确定两个字符串是否指向同一个对象
    • 不会比较字符串的内容是否相等
  • 空串是长度为0的字符串

    • 空串是一个Java对象,有自己的串长度 0 和内容
  • Stringnull,表示没有任何对象与该变量关联,跟空是不同的,空是没有长度的

常用的API方法
  • contains(s1),boolean返回值
    // 字符串中包含"ing",返回true
    System.out.println(str.contains(“ing”)

包装类

万物皆对象,我们调用基本数据类型时,都是包装好的类,我们是直接创建了对应类的对象,然后调用对应的方法
int->Integer


错误与异常

Exception

JVM识别错误代码,并定位提示错误信息,在执行前拦截;

try…catch…finally-尽量用这个

作用:有异常,判断异常,程序还是能正常执行,不会被拦截不能执行,无论有没有错,finally里的是一定会执行的;


throw

谁调用谁处理

  • 格式:
    image

Error

不可预料,代码外的异常

集合:collection(单个) 、map(单对:key value)

概念

多个不同类型的对象数据

collection 接口是List queue set接口的父类接口

  • 可以添加变量,对象
格式

add():集合中添加单个对象

 Collection c1 = new ArrayList();
        c1.add(new String("hello"));  //放在堆区
        System.out.println("c1:"+c1);
        c1.add("zj");  //放在常量池
        System.out.println("c1:"+c1);
        c1.add(77);
        System.out.println("c1:"+c1);

       //c1.add(new Persion(name:"zhaojie",age:88)); //要是想打印出这种格式而不是地址,需要在新建对象的类里添加toString方法,基本八大类型add的时候能直接打印出来添加内容,是因为本身的类有toString方法
        c1.add(new Persion("zhaojie",88));
        System.out.println("c1:"+c1);

addAll():集合中添加多个元素

Collection c2 = new ArrayList();
        c2.add(88);
        c2.add("java");
c1.addAll(c2); //c1:[hello, zj, 77, Persion{name='zhaojie', age=88}, 88, java]
c1.add(c2);  //c1:[hello, zj, 77, Persion{name='zhaojie', age=88}, [88, java]]

判断集合内容

contains():判断集合里有没有某个对象

`boolean b2 = c1.contains(“hello”);
System.out.println(“是否包含:”+b2);

可以直接判断int、string类型,如果要判断对象,则需要在呢这个对象对应的类里面添加equal()、hashCode方法;

containsAll():判断集合里有没有某个元素

集合删除

remove()

删除对象,需要用以下方式删除,注意:只要有一个符合被删除,就会返回true,不会提示

boolean b7 = c1.remove(new Persion("zhaojie",88);
        System.out.println("remove 后的 c1:"+c1);
removeAll()删除集合的每个元素

集合的其他方法

集合转化成数组

c1.toArray().var回车
Object[] objects = c1.toArray();

数组转化成集合

集合-迭代器

概念

  • java.util.Iterator接口
    • 描述迭代器对象
    • ==遍历Collection集合==中的所有对象

方法

方法声明 功能介绍
boolean hasNext() 判断集合中是否有可以迭代/访问的元素
E next() 用于取出一个元素并指向下一个元素
void remove() 用于删除访问到的最后一个元素
 Iterator i1 = c1.iterator();
        while(i1.hasNext()){
 
            System.out.println(i1.next() );
        }
toString加深打印效果


``System.out.println(c1);
// 由于上个循环已经使得迭代器走到了最后,因此需要重置迭代器
iterator = c1.iterator();
StringBuilder s = new StringBuilder();
s.append("[");
while (iterator.hasNext()){
    Object next = iterator.next();
    if(!iterator.hasNext()){
        s.append(next).append("]");
    }else {
        // 否则拼接元素加逗号加空格
        s.append(next).append(",").append(" ");
    }
}
System.out.println(s);
删除

if(d.equals(next)){
c1.remove(next);
}

注意
  • 在迭代过程中不能对集合/数组对象进行操作,否则会报==并发修改异常==

forEach:对数组或集合进行遍历

image

    Collection c1 = new ArrayList();
        c1.add("zhaojie");
        c1.add(99);
        System.out.println("c1:"+c1);

        for (Object obj:c1
             ) {
            System.out.println("foreach:"+obj);
        }

list

  • List集合的主要实现类有:ArrayList类、LinkedList类、Stack类、Vector类。
    • ArrayList类的底层是采用==动态数组==进行数据管理的,支持==下标访问==,==增删元素不方便==。
    • LinkedList类的底层是采用==双向链表==进行数据管理的,==访问不方便==,==增删元素方便==。
    • Stack类的底层是采用==动态数组==进行数据管理的,主要管理的是后进先出特征的数据结构,叫做栈
    • Vector类是比ArrayList类更线程安全的类,但是效率比较低,已过时。每次扩容是2倍。

语法:List arrayList = new ArrayList();
会一次给10个元素的内存,超过10个后会扩容;

#queue

   public static void main(String[] args) {
        Queue queue1 = new LinkedList();

        for (int i = 1;i<6;i++){
            boolean offer1 = queue1.offer(i*11);
        }

        System.out.println("Queen集合元素为:"+queue1);

        //打印队列首位元素peek
        System.out.println("首位元素为:"+queue1.peek());

        //出队元素poll,循环出队
        for(int i=0;i<= queue1.size();i++){
            Object poll1 = queue1.poll();
            System.out.println("出队元素为:"+poll1);

        }

        System.out.println("Queen集合元素为:"+queue1);
    }
}

18-泛型

object是所有类型父类
集合取出元素,也是object类型,要是用元素真实的类型,就要强转

概念

  • 集合名称的右侧使用<数据类型>
    • 明确集合中可以存放的元素类型
    • 若放入其它类型的元素则编译报错
  • 泛型只在编译时期有效,在运行时期不区分是什么类型。
  • <>等号前面不可省略,等号后面的可以省略:List list2 = new ArrayList<>();

自定义泛型

可以声明一个类,然后在类名后<>里自定义类型<E,T…>,后面会沿用这个类型
image

父子类泛型

父类有泛型,子类可以保留泛型也可以指定泛型类型

  • 子类不保留泛型T且没有指定类型(丢弃泛型)
public class SubAnmial extends Anmial{}
  • 子类不保留泛型,但指定了父类的泛型T
public class SubAnmial extends Anmial<String>{}

  • 子类保留父类泛型T
public class SubAnmial<T> extends Anmial<T>{
}
  • 子类增加自己的泛型
public class SubAnmial<T,E> extends Anmial<T>{
}
  • 泛型中有三种通配符形式
    • <?>
      • 无限制通配符
      • 可以传入任意类型的参数
    • <? extends E>
      • 类型的上界是 E
      • 只能是 E 或者是 E 的子类
    • <? super E>
      • 类型的下界是 E
      • 只能是 E 或者是 E 的父类

set集合

二叉树

有序二叉树:

tractset

collect集合是单个集合,Map集合数据是成对出现

Map集合<K,V>

io流:字节流、字符流

写入本地文件:.FileWriter()
读取本地文件:.FileReader(),读取一个,光标往后移动一个

package iop;

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

public class FileReadDemo {
    public static void main(String[] args) throws FileNotFoundException {
        FileReader fileReader  = null;
        try {
            //1. 创建对象;
            fileReader = new FileReader("/Users/a1/Desktop/iotest/io.txt");
/*
            //2. 读取文本中第一个数据;
            int read = fileReader.read();
            System.out.println("读出来的内容:"+read);

            //读取所有数据
            int res = 0;
            while (-1 != (res = fileReader.read())){
                System.out.println("全部内容:"+(char)res);
            }
            
 */

            //读取部分内容
            char[] chars1 = new char[5];
            int read2 = fileReader.read(chars1,1,3);
            System.out.println("取到的个数:"+read2);
            System.out.println(chars1);
           for(char c:chars1){
               System.out.println(c);
           }

        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            try {
                if(null != fileReader){
                    //3.关闭流;
                    fileReader.close();
                }
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }


    }


}

字节流:可以读写所有类型的文件


大文件用BufferInputStream BufferOutStream

stream流

不是任何一种类型,是一种保存数据结构