C++基础下的Java速通

原文地址

原文链接

前言

默认有基础,用于快速回顾Java内容,或者c++向java的速通。如果较真内容可能有偏颇或者歧义并不能完整表达java的各项特性和功能

基础

  • 注意命名,不能使用关键字,不能使用数字或者特殊字符开头除了 $ 和 _
  • 变量根据是否直接被类包含分为成员变量和局部变量
  • 成员变量看是否被static修饰和静态变量和实例变量,前者生命周期取决于类的生命周期,后者取决于实例后的对象
  • 局部变量分为方法局部,方法参数和代码块局部,生命周期为所在块生命周期
  • 循环方式上比c++多一个 for (dataType data : collection) {} 的格式,c11也支持

字符串

  • 使用String创建字符串,字符串的内容是不能更改的,但是可以重新赋值
  • String通过Integer.parseInt(str)和Integer.toString(i);和int量互转
  • String 可以使用 + 和 concat 拼接,+ 可以拼其他格式,concat只能返回String
  • String 可以通过length()获取长度,使用toLowerCase()和toUpperCase转换大小写,使用trim()去掉空格,使用replace()、replaceFirst()、replaceAll(regex, tar)替换字符串,使用subString获取子字符串,使用equal()、compareTo()进行字符串比较,使用indexOf()、charAt()进行字符串查找
  • String中由split方法可以根据提供的分隔字符串,返回String[]类型的数组,使用toCharArray返回Char[]类型的数组
  • StringBuffer 类是可变字符串类,可以更改字符串内容,并且会自动扩容
  • StringBuffer 可以由String直接构造,使用append()添加,使用reverse反转,使用setCharAt()替换,使用deleteCharAt删除,使用delete删除区间,并且支持大部分String的成员函数
  • StringBuilder和Buffer类似,性能更高但是由于不加锁,Buffer线程安全

数字和日期

  • 使用Math中的静态方法实现数学功能 包含各种基本类型的 abs、max、min 和非整型的 ceil floor rint round 以及三角函数、pow指数运算等
  • 使用Math中的random可以通过随机数种子生成伪随机数
  • 使用DecimalFormat使用格式字符串作为构造函数参数,可以对数据格式化
  • 使用BigInteger和BigDecimal可以进行大数据或者高精度的数据运算,BigInteger一般使用成员函数进行运算,java 不能重载运算符
  • Date 可以根据时间戳构造参数获取时间,并且通过after before compareTo 等成员函数进行比较
  • 一般使用 SimpleDateFormat 类来格式化日期,使用pattern字符串初始化类对象设置格式化格式,然后直接调用对象使用成员函数format去格式化date类型,“yyyy-MM-dd E HH:mm:ss:SSS”
  • 在新的代码中,官方的建议是使用LocalDate代替Date,不仅是因为LocalDate有更多的api,还有更优秀设计

包装类

  • 为了支持java一切皆对象的目标,基本数据类型都有包装类
  • Object 是java类库中的一个特殊类,也是所有类的父类,clone(), equal(), toString(), getClass() 等都为所有类可以使用的方法
  • 对于equal(),一般情况下==运算符是比较两个引用变量是否指向同一个实例,equals() 方法是比较两个对象的内容是否相等
  • Number() 是一个抽象类,所有包装类都是Number的子类,定义了doubleValue(), intValue() 等抽象方法给子类实现
  • System类 System.out.println(data); System.in.read(); 以及系统级的操作方法,常用的方法有 currentTimeMillis()、exit()、gc() 和 getProperty()

数组

  • 和c不同,java一般使用 type[] arrayName = new type[size]; 来初始化数组,其他基本操作和c一样
  • 对于二维数组的处理,除了初始化和方式其他的部分和c一样
  • Array中包含 binarySearch(), fill(), sort(), toString(), equal(), copyOf()等很多处理数组的静态方法
  • 使用 String.copyValueOf(charArray) 可以将char[]字符串转换为String,也可以使用StringBuffer循环遍历拼接
  • Arrays.copyOf(), Arrays.copyOfRange(), System.arraycopy(), Object.clone() 都是浅拷贝
  • 对于Array.sort() 如果想要重写拷贝方法需要新建类去实现comparator<T>类的compare方法

类和对象

  • 面对对象的优点:可重用,易拓展,易管理
  • 面对对象的特性:继承,封装,多态
  • 如果类使用abstract或者final其一修饰,分别表示不能被实例化(继承的非抽象子类需要实现所有的抽象方法)和不允许继承,两者相悖,自然不能同时修饰
  • 成员变量中 static 为静态 final 为常量,成员函数 static 标为静态
  • this 可用于任何实例方法内指向当前对象,当一个类的成员变量名与访问该属性的方法参数名相同时,则需要使用 this 关键字来访问类中的属性,以区分类的属性和方法中的参数,还可以在类内使用this()来访问构造方法
  • 和c++一样,static 修饰的方法中不能使用 this,静态成员不能直接访问非静态成员
  • 匿名对象一般是指直接new出来然后作为参数传递没有命名的对象,使用一次之后就等待被 GC(垃圾收集机制)回收
  • 垃圾回收机制是指 JVM 用于释放那些不再使用的对象所占用的内存,java中Object父类提供finalize()对类进行资源相关操作,调用 System.gc() 或者 Runtime.gc() 方法也不能保证回收操作一定执行,它只是提高了 Java 垃圾回收器尽快回收垃圾的可能性
  • jvm的堆区有三种状态,可触及状态、可复活状态,不可触及状态,程序中还有对象引用为可触及,无对象引用时候为可复活状态,在释放之前,若对象未执行过finalize方法且未被覆盖,将其放入队列,由低优先级线程执行队列finalize方法。执行finalize方法完毕后,有可能使该对象重新转到可触及状态,如果没有则为不可触及状态,随时可能被释放
  • 修饰 public 表示任意位置可访问,protect 继承 同包 内部可访问,friendly 默认权限 同包 包内可访问,private 包内可访问,类的权限只有public和默认的包访问权限,如果声明了public他必须和文件名一致
  • 静态代码块指 Java 类中的 static{ } 代码块,主要用于初始化类,为类的静态变量赋初始值,提升程序性能,而{}非静态代码块,则是在对象被创建的时候执行
  • 导入类名.*的包,那么可以在不使用类名的情况下直接调用类的静态方法和静态变量,称为静态导入
  • c++中static可以修饰局部变量,java中不能修饰局部变量,并且和c++不同static在java中不会影响作用域
  • final修饰变量,变量不能修改,只能赋值一次。修饰方法,方法不能被重写。修饰类,类不能被继承
  • main() 方法定义必须是 public static void main(String args[]) {} 格式,一个类只能由一个main方法
  • c++由操作系统调用运行库运行库调用c程序,运行库先初始化环境再处理c程序,是会对c程序的返回值处理的,所以main是有int返回的,但是jvm在被操作系统调用后直接调用了java程序,不会对返回值处理
  • 使用 public void print(String…names) {} 的格式处理可变参数,相当于传入了一个String[],可变参数需要在参数列表的末尾
  • java中构造函数只能与 new 运算符结合使用
  • finalize() 类似c++中的析构函数,可以重写析构方法但是一般不建议这样做

继承和多态

  • 封装:只能通过规定的方法访问数据,隐藏类的实例细节,方便修改和实现
  • 继承:子类实现或者重写父类的方法,或者在父类的基础上添加方法或者成员变量
  • 如果在子类中不含有构造方法,默认会调用父类中无参的构造方法,如果此时父类没有无参构造方法就会出错
  • Java中所有的继承都是 public ,不支持多继承
  • super 关键字可以在子类的构造方法中通过 super() 显式地调用父类的构造方法,而且规定super必须在子类构造方法的第一行,默认子类的构造方法第一行为 super() 可以不写,调用父类的无参构造方法,可以使用 super. 访问父类对象的成员,使用方法和this类似
  • 和c++一样,java的向上转型是安全的,向下转型的必须要是对象本身指向的为子类才行,向上转型直接赋值就可以,向下转型需要使用强制类型转换,使用instanceof if (Animal instanceof Cat) {} 判断animal指向的是否为子类Cat,判断原理猜测就是c++的RTTI机制
  • 同c++,使用允许向上转型,虽然不能让父类对象使用子类的成员变量和方法但是可以让父类对象根据传入参数的不同在重写方法上表现出不一样的特性, 体现了多态
  • 常用instanceof作为向下转型的前置判断条件,一般用于取消多态性,直接调用子类方法
  • java 实现多态有 3 个必要条件:继承、重写和向上转型
  • abstract 抽象方法没有方法体,必须为于抽象类当中,子类重写父类时,必须重写所有抽象方法,抽象类可以有具体方法,但是不能实例化,构造方法只能被子类调用
  • interface 接口只能由全局静态常量和公共抽象方法组成,接口也可以继承,接口没由构造方法不能被实例化,只能被实现,默认修饰符为public,不能使用其他修饰符,但是是可以有接口对象的直接 InterfaceClass name; 即可,使用name调用方法
  • 抽象类主要是为了继承的特性实现多态,接口类主要是为了实现
  • 内部类为定义在类内部的类,内部类拥有外部类的所有元素的访问权限,分为实例内部类、静态内部类和局部内部类,外部类只有两种访问级别,内部类有四种
  • 实例内部类是指没有用 static 修饰的内部类,通过 new Outer().new Inner() 创建,在实例内部类中不能定义 static 成员,除非同时使用 final 和 static 修饰
  • 静态内部类是指使用 static 修饰的内部类,通过 new Outer.Inner() 创建,静态内部类中可以定义静态成员和实例成员,可以直接访问外部类静态成员,不能直接访问外部类的实例成员
  • 局部内部类是指在一个方法中定义的内部类,和局部变量一样不能使用控制修饰符,不能定义static成员,只可以访问当前方法中 final 类型的参数与变量
  • 匿名类是指没有类名的内部类,必须在创建时使用 new ClassName/InterfaceName() {}; 语句来声明类,匿名类一般用于重写类实现,或者实现接口类,减少开发量,接口匿名类例子
  • 内部类可以继承一个与外部类无关的类,从而保证内部类的独立性,所以利用这个特性可以实现多继承,建立两个内部类去继承其他类,该类就可以通过访问内部类来实现多继承
  • 局部内部类和匿名内部类访问的局部变量必须由 final 修饰,保证内外的一致性,java8之后添加了 effectively final 会自动添加final
  • lambda表达式,InterfaceClass res = (int a, int b) -> { return a+b }; 最省略的格式甚至可以写成 InterfaceClass res = a -> a * a * a; 可以在lambda表达式中实现/重写接口,返回接口对象提供重写后的功能以供使用
  • lambda表达式的一个重要用法是简化某些匿名内部类的写法,因此它可以部分取代匿名内部类的作用,当接口只有一个抽象方法这种称为函数式接口,lambda表达式只能应用于这样的接口,其他限制不赘述

异常

  • 异常都是Throwable的子类,包含Error和Exception,Exception又包含运行时异常和非运行时异常

  • Exception 类用于用户程序可能出现的异常情况。Error 定义了在通常环境下不希望被程序捕获的异常,一般指的是 JVM 错误,如堆栈溢出,通常是灾难性的

  • 常见运行时异常:ClassCastException 类型转换异常,NullPointerException 空指针异常,ArraylndexOutOfBoundException 数组越界异常

  • 场景非运行时异常:ClassNotFoundException 类未找到异常,NoSuchMethodException 方法不存在异常

  • 错误:OutOfMemoryError 栈溢出

  • try catch 语句用于捕获并处理异常,finally 语句用于在任何情况下(除非在catch或者try的时候程序终止)都必须执行的代码,throw 语句用于拋出异常,throws 语句用于在方法上声明该方法可能要拋出的异常

  • 多重 catch 只会捕获第一个匹配

  • 当 try 代码块或者 catch 代码块中有 return 时,finally 中的代码总会被执行,如果finally中有return会直接return,但是在finally值修改return值,不会在try,catch中return时生效

  • 使用 try() {} catch() {} 在try的参数列表中使用申请资源的语句,分号隔开,那么就不用再finally中考虑释放资源可能会再次触发异常的可能性了,系统会自动释放,也可以用资源参数代替资源申请语句

    // 没有显式使用final修饰,但只要不对该变量重新赋值,该变量就是有效的
    final BufferedReader br = new BufferedReader(new FileReader("AutoCloseTest.java"));
    final PrintStream ps = new PrintStream(new FileOutputStream("a. txt"));
    try (br; ps) {
        System.out.println(br.readLine());
        ps.println("======");
    }            
            
    
  • 子类重写方法时,声明抛出的异常类型应该是父类方法声明抛出的异常类型的子类或相同,子类方法声明抛出的异常不允许超过父类异常范围

  • throw 语句用来直接拋出一个异常,异常只能是 Throwable 类或其子类的对象

  • 当一个类可能会触发 throw 时并且没有捕获时,调用他的类要么 throws 抛给上级,要么捕获住

  • 在catch( Exception1 | Exception2 ) {} 捕获多种异常一种处理

  • 可以通过继承 Exception 自定义异常

集合、泛型、枚举

  • Iterator类的子类为Collection类,Collection的子类有Queue, List, Set,键值对的类为Map类,下面有HashMap等子类

  • Collection有一些通用的方法被子类复写,add(), addAll(), clear(), contains(), containsAll(), isEmpty(), remove(), removeAll(), retain(), size(), toArray()

  • List常用的为两个实现类,ArrayList和LinkList,ArrayList默认构造函数为10容量空列表,也可以使用Collection类初始化,底层使用数组,拥有数组存储的特性,LinkedList 类采用链表结构,具有链表存储的特性,常用函数 sort(), reverse()

  • Set 集合中不能包含重复的对象,主要两个实现类 HashSet 和 TreeSet,HashSet同样有无参和Collection参的构造函数,hashCode 值相等且通过 equals() 方法比较返回结果为 true,则 HashSet 集合认为两个元素相等,如果向 Set 集合中添加两个相同的元素,则后添加的会覆盖前面添加的元素,即在 Set 集合中不会出现相同的元素,一般使用Iterator来遍历HashSet 或者使用for循环遍历

    Iterator<String> it = courseSet.iterator();
    while (it.hasNext()) {
        System.out.println("《" + (String) it.next() + "》");
    }
    
  • TreeSet 类同时实现了 Set 接口和 SortedSet 接口,TreeSet 只能对实现了 Comparable 接口的类对象进行排序,遍历方法和Hash类似,常用方法headSet(), tailSet(), subSet(), first(), last()

  • Map 同样不允许键重复,接口主要有两个实现类,HashMap 类和 TreeMap 类,常用方法有,get(),put(), putAll(), containKey(), containValue(), remove(), entrySet(), keySet(), values(),

  • 使用keySet或者entrySet来通过for循环遍历Map,也可以通过迭代器遍历

  • 使用foreach可以利用lambda表达式遍历Collection类及其子类

    sSet.forEach(str -> log.info("{}", str));
    iSMap.forEach((key, value)-> log.info("{} {}", key, value));
    
  • Iterator(迭代器)是一个接口,它的作用就是遍历Collection类的所有元素,常用方法有hasNext(), next(), remove() 可用remove() 方法来删除集合中上一次 next() 方法返回的集合元素,当使用 Iterator 循环迭代访问 Collection 集合元素时,Collection 集合里的元素不能被改变,迭代器采用的是快速失败(fail-fast)机制,一旦在迭代过程中检测到该集合已经被修改(通常是程序中的其他线程修改),程序立即引发 ConcurrentModificationException 异常,而不是显示修改后的结果,这样可以避免共享资源而引发的潜在问题。

  • Collection中可以使用removeIf的方式来实现对于特定元素的删除

    objs.removeIf(ele -> ((String) ele).length() < 12);
    
  • Stream 是一个通用的流接口,而 IntStream、LongStream、 DoubleStream 则是各种类型的流,Stream 或 XxxStream 的 builder() 类方法创建该 Stream 对应的 Builder,重复调用 Builder 的 add() 方法向该流中添加多个元素,最后调用 Builder 的 build() 方法获取对应的 Stream

  • 流操作,流操作可以自己通过 IntStream is = IntStream.builder().add(20).add(13).add(-2).add(18).build(); 这样的语句建立的流,也可以是Collection类通过 objs.stream() 转换出的流

  • 流提供大量的方法,分为允许直接调用后续方法的中间方法和消耗流本身的末端方法

  • 常用的中间方法有:正向过滤 filter,类型转换 mapToXxx,去重排序 distinct,排序 sort

  • 常用的末端方法有:转化 collection toArray,遍历执行 foreach,合并元素 reduce,以及max min count 等

  • 使用 .of 创建的方法可以创建不可变集合,即不能向集合中添加元素,也不能从集合中删除元素

    Set set = Set.of("Java", "Kotlin", "Go", "Swift");
    Map map = Map.of("语文", 89, "数学", 82, "英语", 92);
    Map map2 = Map.ofEntries(Map.entry("语文", 89), Map.entry("数学", 82), Map.entry("英语", 92));
    List list = List.of(34, -25, 67, 231);
    
  • 集合初始化

    String[] str =new String[4];
    String[] str = new String[] {"1", "2"};
    String[] str = {"1", "2"};
    
    String[] str = new String[5];
    Arrays.fill(str, "411");
    double[][] arr = new double[20][4];
    Arrays.stream(arr).forEach(a -> Arrays.fill(a, 0));
    
    List<String> list = new ArrayList();
    list.add("4");
    List<String> list = new ArrayList<>(Arrays.asList("1", "2", "3"));
    
    Set testSet = new HashSet();
    testSet.add("Monday");
        Iterator<String> it = courseSet.iterator();
        while (it.hasNext()) {
            System.out.println("《" + (String) it.next() + "》"); // 输出 Set 集合中的元素
        }
    
    HashMap users = new HashMap();
            users.put("11", "张浩太");
    Iterator it = users.keySet().iterator();
            while (it.hasNext()) {
                // 遍历 Map
                Object key = it.next();
                Object val = users.get(key);
                System.out.println("学号:" + key + ",姓名:" + val);
            }
    
    for (String key : map.keySet()) {
        System.out.println(key);
    }
    

反射

反射机制指的是程序在运行时能够获取自身的信息。在 Java 中,只要给定类/对象的名字,就可以通过反射机制来获得类的所有信息,通过Object类的getClass获取Class对象,可以获得包含包路径,类名称,继承类,实现接口构造方法,方法,成员,内部类等所有信息

注解

无论是哪一种注解,本质上都一种数据类型,是一种接口类型

注解常见功能:

  • 生成帮助文档 @see @param @return
  • 跟踪代码依赖性,实现替代配置文件功能
  • 在编译时进行格式检查 @Override
  • 元注解,解释其他注解 @Override、@Deprecated、@SuppressWarnings、@SafeVarargs 和 @FunctionalInterface

@Override

指定方法重写的,只能修饰方法并且只能用于方法重写,不能修饰其它的元素,它可以强制一个子类必须重写父类某个方法或者实现接口的某个方法,所以 @Override 的作用是告诉编译器检查这个方法,保证父类要包含一个被该方法重写的方法,否则就会编译出错

@Deprecated

可以用来注解类、接口、成员方法和成员变量等,用于表示某个元素(类、方法等)已过时。当其他程序使用已过时的元素时,编译器将会给出警告,有两个属性,since(String) 指定过期版本,forRemoval(boolean) 未来是否会被删除

@SuppressWarnings

注解指示被该注解修饰的程序元素(以及该程序元素中的所有子元素)取消显示指定的编译器警告,且会一直作用于该程序元素的所有子元素

@SuppressWarnings("unchecked")
@SuppressWarnings({"unchecked","rawtypes"})
@SuppressWarnings("all")

@FunctionalInterface

对于 Lambda 表达式时,如果接口中只有一个抽象方法(可以包含多个default方法或多个 static 方法),那么该接口就是函数式接口。@FunctionalInterface 就是用来指定某个接口必须是函数式接口,所以 @FunInterface 只能修饰接口,不能修饰其它程序元素

@SafeVarargs

效果和 @SuppressWarnings(“unchecked”) 一样,在static方法或者final方法上,对于泛型可变参数,提供不同不同类型时候,可以用这个注解取消警告

@SafeVarargs
public static <T> void display(T... array) {
    for (T arg : array) {
        System.out.println(arg.getClass().getName() + ":" + arg);
    }
}

@Override
public void test() {
    display("10", 20, 30);
}

原文地址

原文链接

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值