21Java进阶练习题整理(3)

1.集合

List a = new ArrayList();
a.add(1);
a.add(2);
a.add(3);
a.remove(1);
    public E remove(int index); //执行删除指定位置的元素的功能
    public boolean remove(Object o)  //执行删除指定元素的功能

如果传入参数是int(自动装箱为Integer)时,调用哪个方法?
应该调用删除指定位置元素的方法,因为重载方法会优先调用参数类型最符合类型的(相等,或最小包含的)。

在这里插入图片描述
List泛型写法:

		//      <> 左有 左无 左有值 右有 右无 右有值 共9种
        //      其中<>左有是非法的 9-3 =6种
        //      剩下6种都是合法的
        //      其中<>左无的list没有特定的泛型,add()任何对象都可以
        //      但是<>左有值的list只能添加泛型类型,否则会编译错误
        //List list = new ArrayList();      <>都没有
        //List list = new ArrayList<>();    <>右边有,左边没有
        List list = new ArrayList<Student145>();
        //List<Student145> list = new ArrayList();  <>左边有值,右边没有
        //List<Student145> list = new ArrayList<>();
        //List<Student145> list = new ArrayList<Student145>();

在这里插入图片描述

在这里插入图片描述
接口:Map接口,Map子接口Entry、SortedMap、NavigableMap
子类:HashMap、TreeMap、HashTable、LinkedHashMap

在这里插入图片描述
接口:Collection (继承自Iterable接口)、Iterator接口(子接口ListIterator) 子接口有Set(子接口SortedSet、NavigableSet)、List、Deque、Queue
子类:Vector、ArrayList、LinkedList(List子类)、ArrayDeque、PriorityQueue、HashSet、LinkedHashSet、TreeSet

在这里插入图片描述
虽然使用HashMap会浪费空间,但是HashMap底层是位桶数组+链表+红黑树实现,比LinkedList链表实现查询会快很多。
集合子类的底层实现:

在这里插入图片描述
Collections中包含很多有关集合操作的类方法。

在这里插入图片描述
泛型与强制类型转换的关系是针对于:
jdk5之前没有泛型,声明一个List时,使用

List list = new ArrayList();

这样的形式,加入元素没有类型限制,但是对于取出元素,就要对每个元素进行强制类型转换,很容易出现ClassCastException运行时异常。
提出泛型后,限制了集合的类型,要声明一个泛型List:

List<String> list  = new ArrayList<>();

泛型List对放入的集合元素有类型限制,但是取出元素,不需要再进行强制类型转换。

2.IO

//假设文件 c:/a.txt 的内容为 abc
try {
    File f = new File("c:/a.txt");
    System.out.print(f.length());
    OutputStream out = new FileOutputStream(f);
    System.out.print(f.length());
    out.write(97);
    System.out.print(f.length());
    out.close();
} catch (FileNotFoundException e) {
    e.printStackTrace();
} catch (IOException e) {
    e.printStackTrace();
}
//执行后,控制台输出为?

File类中的length():
如果文件不存在/文件是目录且为空/文件为空,都返回0。
返回的是字节数,一个英文字母/数字是1字节,一个汉字是3字节(utf-8编码,如果是GB2312/ANSI编码是2字节,UTF16是4字节,带有BOM的UTF-8是6字节)

以下哪个流可以将数据写入到内存中?ByteArrayOutputStream
bais/baos不是将数据写入硬盘,而是写入内存。内存的数据在断电后不会被保存。

try {
    FileWriter w = new FileWriter("c:/a.txt");
    w.write("abc");
    w.append("world");
    w.write("kof98");
    w.close();
} catch (IOException e) {
    e.printStackTrace();
} 

FileWriter中write()和append()区别:

  1. append参数可以写null,write写null会报错。因为write方法的参数是char,以及数组/String和下标,不可以为null,否则会编译错误或者空指针。但是append的参数除了char还可以是CharSequence。
  2. write()后面不可以跟write(),但是append()后面可以跟append()。因为write()返回值是void,append()返回当前Writer对象。
   @Override
    public Writer append(CharSequence csq) throws IOException {
        if (csq instanceof CharBuffer) {
            se.write((CharBuffer) csq);
        } else {
            se.write(String.valueOf(csq));
        }
        return this;
    }
    
	public void write(int c) throws IOException {
        se.write(c);
    }
  1. 相同点:作用一样,都是写入文件。不执行flush()或者不执行close()不会写入文件。

在这里插入图片描述
注意转义符号。

在这里插入图片描述
静态导入是jdk5的新特性,作用是导入静态的成员,比如类中的静态方法或者静态变量。
语法是import static 包名.类名.静态成员名,也可以是import static 包名.类名.*导入类中所有的静态成员。
静态导入的作用是导入后可以直接使用静态方法名和静态变量名,比如

import static java.lang.System.*;


out.println("");
setIn(new FileInputStream(new File("")));

public static final PrintStream out = null;
public static void setIn(InputStream in) {
        checkIO();
        setIn0(in);
    }

可以直接使用System类中的静态对象out,不需要带类名。
但是静态导入也可能和类中同名的变量/方法冲突。

3.反射

在这里插入图片描述
题目错误
forName()是Class类中的静态方法。

[单选]
以下代码
import java.lang.reflect.Method;

public class Test {
    private String name;

    private void eat(int num,String food) {
        System.out.print("吃"+num+"个"+food);
    }

    public static void main(String[] args) {
        try {
            Class c = Class.forName("Test");
            Test t1 = (Test)c.newInstance();
            Method m = c.getDeclaredMethod("eat", int.class,String.class);
            m.invoke(t1, 3,"面包");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
执行后,控制台输出为?

Method类中的invoke()方法:

 public Object invoke(Object obj, Object... args)
        throws IllegalAccessException, IllegalArgumentException,
           InvocationTargetException{...}

调用的Method的对象是通过反射获取的方法对象,第一个参数不可以省略,代表通过反射获取的实例对象,后面的参数可以省略,代表实参列表。

public class Test {
    private String name;
    public int age;

    public Test(String name, int age) {
        this.name = name;
        this.age = age;
    }

    private Test(String name) {
        this.name = name;
    }

    Test(int age) {
        this.age = age;
    }

    public static void main(String[] args) {
        try {
            Class c = Class.forName("Test");
            Test t = (Test)c.newInstance();
            System.out.println(t.name);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

反射中创建新对象的方法:
Class.newInstance() 只能够调用无参的构造函数,即默认的构造函数;
Constructor.newInstance() 可以根据传入的参数,调用任意构造构造函数。
当类中存在其他有参构造函数,且不存在无参构造函数的时候,使用无参构造方法会抛出异常InstantiationException,是一个运行时异常。

如果forName()的类名和实际类名不符,会抛出ClassNotFoundException异常,是非检查时异常,也不是运行时异常。
如果存在无参构造方法,但是权限访问不到,Class.newInstance()方法会抛出IllegalAccessException异常,也是一个运行时异常。
Constructor的成员方法也会抛出这两个异常,还会抛出非法参数异常,以及InvocationTargetException,是当被调用的方法的内部抛出了异常而没有被捕获时,将此异常会将其接收。

4.多线程

在这里插入图片描述
线程进入等待状态后,对该锁发出notify()方法后,线程会进入就绪状态而不是运行状态。

在这里插入图片描述
线程的优先级的作用:
优先级高的线程获得更多的时间片,优先级较低的线程获得较少的时间片。所以与线程的执行顺序没有关系,但是相同的任务量,优先级高的线程在较少的轮转次数(或者时间片没用完)就会执行完,而优先级低的线程会在后面执行完。

在这里插入图片描述
sleep()让线程进入阻塞状态
yield()让线程进入就绪状态。

setDaemon() 的作用是将指定的线程设置成后台线程,说法正确。后台进程等价于守护线程。
在这里插入图片描述
对某个对象调用wait()方法不一定会让当前线程等待,因为它可能属于其他线程。

在这里插入图片描述

多线程:
因为共享进程数据,数据共享简单,但也是因为这个原因导致同步复杂
占用内存少,切换简单,CPU利用率高
创建销毁、切换简单,速度很快
改善程序结构。一个既长又复杂的进程可以考虑分为多个线程,成为几个独立或半独立的运行部分,这样的程序会利于理解和修改。
线程的调度不需要内核直接参与,控制简单。CPU调度还是以进程为单位

5.异常

try-catch-finally可能的执行流程:
(1)try、catch、finally都没有return语句或system.exit(0):执行完块往下接着运行
(2)try/catch有return;,finally没return:有无异常进不同的块,如果该块中有return,会执行完finally再回来return;
(3)try/catch有return;,finally也有return:最终执行finally中的return;
(4)try/catch中有system.exit(0):遇到system.exit(0)直接退出程序
(5)多个catch块,父异常在子异常块前面:编译错误
(6)多个catch块,子异常在父异常块前面:该进哪个进哪个

6.比较器的compareTo()

Comparable:

  @Override
    public int compareTo(Student145 s) {
        //comparable需要一个参数,当this的数-参数的数>0,或者this的数大于参数的数返回1时,是升序排序
        //否则是降序排序
        //return this.getAge()>s.getAge()?1:-1;//按照升序排序
        //return s.getAge()>this.getAge()?1:-1;//按照降序排序
        //return this.getAge()-s.getAge();//按照升序排序
        //return s.getAge()-this.getAge();//按照降序排序
        return 0;
    }

Comparator:

 Comparator<Student145> comparator = new Comparator<Student145>() {
            @Override
            //comparator需要两个参数,当返回第一个数-第二个数,或者第一个数大于第二个数返回1时,是升序排序。
            //否则是降序排序。
            public int compare(Student145 s1, Student145 s2) {
                //return s1.getAge()>s2.getAge()?1:-1;//按年龄升序排序
                //return s2.getAge()>s1.getAge()?1:-1;//按年龄降序排序
                //return s1.getAge()-s2.getAge();//按年龄升序排序
                //return s2.getAge()-s1.getAge();//按年龄降序排序
                return 0;
            }
        };

stream.max((Object a,Object b)->{return (Integer)a-(Integer)b;}).get())
属于外部比较器,第一个减第二个的形式,所以是升序排序。
max(),get()实际上是取最后一个(升序排序最大值,降序排序最小值)。
原理是,max()会留下两个数比较,比较器返回正数的那个数字(对象),这样留下的永远是最大(1)的。

  List<Integer> list = new ArrayList<>();
        list.add(10);
        list.add(11);
        list.add(12);
        list.add(5);
        list.add(6);
        Stream<Integer> s = list.stream();
        //猜想 正数就留下第一个, 负数就留下第二个
        //比较过程是 10&11  11&12 12&5 12&6 留下12
        System.out.println( s.max((Integer a,Integer b)->(a-b)).get());//等价于Integer::compareTo
        s = list.stream();
        //比较过程是 10&11 10&12 10&5 5&6 留下5
        System.out.println( s.max((Integer a,Integer b)->(b-a)).get());
        s = list.stream();
        //比较过程是 10&11 10&12 10&5 10&6 留下10
        System.out.println( s.max(Integer::max).get());

        List<Integer> list2 = new ArrayList<>();
        list2.add(-1);
        list2.add(-2);
        list2.add(-3);
        list2.add(-4);
        list2.add(-5);
        list2.add(-6);
        s = list2.stream();
        //比较过程是 -1&-2 -2&-3 -3&-4 -4&-5 -5&-6 最后留下-6
        System.out.println( s.max(Integer::max).get());

7.正则表达式

\w 匹配字母或数字或下划线或汉字 等价于 ‘[^A-Za-z0-9_]’。
\s 匹配任意的空白符
\d 匹配数字
\b 匹配单词的开始或结束。\b匹配这样的结构:\b两边,一边是单词的字母\w,一边是隐式占位符(?)。比如a\bnice是非法的,\bnice\b会匹配到n开头e结尾的,er\b可以匹配到r结尾的单词。
{n}表示匹配的长度

8.java.net

在这里插入图片描述
URL 类所指向的资源可以是简单的文件或目录,也可以是对更为复杂的对象的引用,例如对数据库或搜索引擎的查询

class InetAddress implements java.io.Serializable
InetAddress不是抽象类,但是无参构造方法是default修饰的。

 InetAddress() {
        holder = new InetAddressHolder();
    }

常用的是get开头获取InetAddress实例
在这里插入图片描述

在这里插入图片描述
osi七层模型最上面三层:应用层、表示层、会话层

在这里插入图片描述
阻塞是指程序会一直等待该方法完成期间不做其他事情。
ServerSocket的accept方法就是一直等待客户端连接。这里的阻塞是指调用结果返回之前,当前线程会被挂起,直到得到结果之后才会返回。

9.注解

在这里插入图片描述
RetentionPolicy.SOURCE表示保留到.java源文件期间,编译不再保留注释。

在这里插入图片描述
javadoc会忽略注解,但是使用@Documented修饰的注解不会被忽略掉。
使用@Documented修饰的注解中,只有成员方法没有成员变量。
在这里插入图片描述
@Override的作用是重写不是重载。重载不需要注解。

10.接口新特性

interface M{
    public default void a() {
        System.out.println("1");
    }
}
interface N{
    public default void a() {
        System.out.println("2");
    }
}
public class A implements M,N {
    public static void main(String[] args) {
        new A().a();
    }
}

执行后,控制台输出为?编译报错还是执行报错

实现多个接口,接口中有同名的默认方法,如果不在实现类/子接口中重写,会报编译错误。

11.重复注解

在这里插入图片描述
重复注解是jdk8的一个新特性,jdk8以前不可以使用多个相同注解修饰同一对象。
重复注解定义:

import java.lang.annotation.Repeatable;
//包装类 成员变量是注解数组 方法名和注解成员方法同名
@interface Authorities {
    Authority[] value();
}
//需要用@Repeatable(包装类.class)修饰
@Repeatable(Authorities.class)
public @interface Authority {
    String value();//成员方法
}
//使用多个相同注解修饰
@Authority(value = "Admin")
@Authority(value = "Manager")
interface AuthorityInterface {
}

12.stream

在这里插入图片描述
生成Stream的方法:
Collection.stream();
Collection.parallelStream();

Stream类的中间方法,返回值也是Stream
Stream.empty();返回空stream
Stream.of(T t)、Stream.ofNullable(T t)、Stream.of(T… values):返回单个元素的stream
Stream.build();
Arrays.stream(T[] array)、Arrays.stream(T[] array,int a,int b);

Stream.max()方法返回的是一个Optional对象,也就是可能为空的对象。

在这里插入图片描述
Stream.map()的参数是一个Function函数式接口,也就是传入一个对象,返回与他有一定联系的另一个类型的值。

12.Lambda表达式、函数式接口

在这里插入图片描述
使用Lambda表达式创建Runnable对象,要符合run()方法的声明:
返回值为 void 参数列表为空。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值