java小记(2)

包装类

 1)基本数据类型就不是对象。但是我们在实际应用中经常需要将基本数据转化成对象,以便于操作。为了解决这个不足,Java在设计类时为每个基本数据类型设计了一个对应的类进行代表,这样八个和基本数据类型对应的类统称为包装类(Wrapper Class)。

####除了Integer和Character类以外,其它六个类的类名和基本数据类型一致,只是类名的第一个字母大写而已。

#####除了Character和Boolean以外,其他的都是“数字型”,“数字型”都是java.lang.Number的子类。

#####Number类是抽象类,因此它的抽象方法,所有子类都需要提供实现。Number类提供了抽象方法:intValue()、longValue()、floatValue()、doubleValue(),意味着所有的“数字型”包装类都可以互相转型。

格式:以Integer为例子//注意Integer.valueOf 和 Integer.parseInt的使用

###包装类每种基本数据类型的相关属性如最大值、最小值等,以及相关的操作方法(这些操作方法的作用是在基本数据类型、包装类对象、字符串之间提供相互之间的转化!)。

 2)自动装箱和拆箱

自动装箱:基本类型的数据处于需要对象的环境中时,会自动转为“对象

自动拆箱:对象自动转成数据类型,且不会显式调用intValue()、doubleValue()等转型方法。

//注意空指针异常问题

3)包装类的缓存问题

 @@@整型、char类型所对应的包装类,在自动装箱时,对于-128~127之间的值会进行缓存处理,其目的是提高效率。

@@缓存处理的原理为:如果数据在-128~127这个区间,那么在类加载时就已经为该区间的每个数值创建了对象,并将这256个对象存放到一个名为cache的数组中。每当自动装箱过程发生时(或者手动调用valueOf()时),就会先判断数据是否在该区间,如果在则直接获取数组中对应的包装类对象的引用,如果不在该区间,则会通过new调用包装类的构造方法来创建对象。

 //包装类在自动装箱时为了提高效率,对于-128~127之间的值会进行缓存处理。超过范围后,对象之间不能再使用==进行数值的比较,而是使用equals方法。

String类

1) String 类对象代表不可变的Unicode字符序列,因此String对象称为“不可变对象”//指的是对象内部的成员变量的值无法再改变。//String类的源码:privated final char[]

//String的某些方法,比如:substring()是对字符串的截取操作,但本质是读取原字符串内容生成了新的字符串。

//在遇到字符串常量之间的拼接时,编译器会做出优化,即在编译期间就会完成字符串的拼接。因此,在使用==进行String对象之间的比较时

2)StringBuffer和StringBuilder

@@均代表可变的字符序列。 这两个类都是抽象类AbstractStringBuilder的子类,方法几乎一模一样 ,内部也是一个字符数组,但这个字符数组没有用final修饰,随时可以修改

@@StringBuffe线程安全,效率较低。StringBuilder线程不安全(一般不会涉及线程安全问题),效率较高。 建议采用该类。

方法:

 1. 重载的public StringBuilder append(…)方法,可以为该StringBuilder 对象添加字符序列,仍然返回自身对象。

 2. 方法 public StringBuilder delete(int start,int end)可以删除从start开始到end-1为止的一段字符序列,仍然返回自身对象。

 3. 方法 public StringBuilder deleteCharAt(int index)移除此序列指定位置上的 char,仍然返回自身对象。

 4. 重载的public StringBuilder insert(…)方法,可以为该StringBuilder 对象在指定位置插入字符序列,仍然返回自身对象。

 5. 方法 public StringBuilder reverse()用于将字符序列逆序,仍然返回自身对象。

 6. 方法 public String toString() 返回此序列中数据的字符串表示形式。

3)不可变和可变字符序列使用陷阱

@@String字符串的操作实际上是对其副本(原始拷贝)的操作,原来的字符串一点都没有改变//String s ="a"; 创建了一个字符串s = s+"b"; 实际上原来的"a"字符串对象已经丢弃了,现在又产生了另一个字符串s+"b"(也就是"ab")。

@@如果多次执行这些改变串内容的操作,会影响程序的时间和空间性能,造成服务器的崩溃。

 @@而StringBuilder和StringBuffer类是对原字符串本身操作的,可以对字符串进行修改而不产生副本拷贝或者产生少量的副本。因此可以在循环中使用。

时间处理相关类

1)long类型的变量来表示时间(从基准时间往前几亿年,往后几亿年都能表示)。

2)获得现在时刻的“时刻数值”,可以使用:long now = System.currentTimeMillis();

需要学习的内容大概如下

 @@Date时间类(java.util.Date)

      1. Date() 分配一个Date对象,并初始化此对象为系统当前的日期和时间,可以精确到毫秒)。

      2. Date(long date) 分配 Date 对象并初始化此对象,以表示自从标准基准时间(称为“历元(epoch)”,即 1970 年 1 月 1 日 00:00:00 GMT)以来的指定毫秒数。

      3. boolean after(Date when) 测试此日期是否在指定日期之后。

      4. booleanbefore(Date when) 测试此日期是否在指定日期之前。

      5. boolean equals(Object obj) 比较两个日期的相等性。

      6. long getTime() 返回自 1970 年 1 月 1 日 00:00:00 GMT 以来此 Date 对象表示的毫秒数。

      7. String toString() 把此 Date 对象转换为以下形式的 String:

    dow mon dd hh:mm:ss zzz yyyy 其中: dow 是一周中的某一天 (Sun、 Mon、Tue、Wed、 Thu、 Fri、 Sat)。

 DateFormat类

作用: 把时间对象转化成指定格式的字符串。反之,把指定格式的字符串转化成时间对象

attention:  DateFormat是一个抽象类,一般使用它的的子类SimpleDateFormat类来实现。

 时间格式字符也可以为我们提供其他的便利。比如:获得当前时间是今年的第几天。代码如下:

 Calendar 类

 Calendar 类是一个抽象类,为我们提供了关于日期计算的相关功能,比如:年、月、日、时、分、秒的展示和计算。M

 GregorianCalendar 是 Calendar 的一个具体子类,提供了世界上大多数国家/地区使用的标准日历系统。

注意月份的表示:一月是0,二月是1,以此类推,12月是11。 因为大多数人习惯于使用单词而不是使用数字来表示月份,这样程序也许更易读,父类Calendar使用常量来表示月份:JANUARY、FEBRUARY等等。

  Math类(用于科学计算)

      1. abs 绝对值

      2. acos,asin,atan,cos,sin,tan 三角函数

      3. sqrt 平方根

      4. pow(double a, double b) a的b次幂

      5. max(double a, double b) 取大值

      6. min(double a, double b) 取小值

      7. ceil(double a) 大于a的最小整数

      8. floor(double a) 小于a的最大整数

      9. random() 返回 0.0 到 1.0 的随机数

      10. long round(double a) double型的数据a转换为long型(四舍五入)

      11. toDegrees(double angrad) 弧度->角度

      12. toRadians(double angdeg) 角度->弧度

File类的基本用法(io流经常使用)

1)java.io.File类:代表文件和目录。 在开发中,读取文件、生成文件、删除文件、修改文件的属性时经常会用到本类。

2)File类的常见构造方法:public File(String pathname)

3)以pathname为路径创建File对象,如果pathname是相对路径,则默认的当前路径在系统属性user.dir中存储

4) File f=new File("d/a.text")//在d盘下有一个名为text的文件也可以为d\\a.text

  5)使用mkdir创建目录

         File f = new File("d:/c.txt");

        f.createNewFile(); // 会在d盘下面生成c.txt文件

        f.delete(); // 将该文件或目录从硬盘上删除

        File f2 = new File("d:/电影/华 语/大陆");

        boolean flag = f2.mkdir()//目录结构中有一个不存在,则不会创建整个目录树

        System.out.println(flag);//创建失败

*************************************************************************************************************

        File f = new File("d:/c.txt");

        f.createNewFile(); // 会在d盘下面生成c.txt文件

        f.delete(); // 将该文件或目录从硬盘上删除

        File f2 = new File("d:/电影/华语/大陆");

        boolean flag = f2.mkdirs();//目录结构中有一个不存在也没关系;创建整个目录树

        System.out.println(flag);//创建成功

递归遍历目录结构和树状展现

作用:处理目录下所有文件,读取文件

枚举

特点:枚举体用来放置一些常量,常量通常用大写字母表示

格式

     enum  枚举名 {         

         枚举体(常量列表) }    

注意: 尽量不要使用枚举的高级特性。

异常(Exception)

1)Java的异常机制

try {

    copyFile("d:/a.txt","e:/a.txt");   //发现异常

} catch (Exception e) {

    e.printStackTrace();      //捕获异常

}

2)Exception概念

@运行过程中出现的非正常现象,例如用户输入错误、除数为零、需要处理的文件不存在、数组下标越界等。

 @在Java的异常处理机制中,引进了很多用来描述和处理异常的类,称为异常类。异常类定义中包含了该类异常的信息和对异常进行处理的方法。

@ 异常处理:就是指程序在出现问题时依然可以正确的执行完。

3)异常的分类

Java对异常进行了分类,不同类型的异常分别用不同的Java类表示,所有异常的根类为  java.lang.Throwable,Throwable下面又派生了两个子类:Error和Exception

  Error是程序无法处理的错误,表示运行应用程序中较严重问题,   Exception是程序本身能够处理的异常。

4)RuntimeException运行时异常

 派生于RuntimeException的异常,如被 0 除、数组下标越界、空指针。需要通过增加“逻辑处理来避免这些异常”

@被 0 除(ArithmeticException)

public class Test3 {

    public static void main(String[] args) {

        int b=0;

        System.out.println(1/b);

    }

}  // 会声明错误

增加逻辑判断后

public class Test3 {

    public static void main(String[] args) {

        int b=0;

        if(b!=0){

            System.out.println(1/b);

        }

    }

}

@空指针异常(NullPointerException)

增加逻辑判断

public class Test4 {

    public static void main(String[] args) {

        String str=null;

        if(str!=null){

            System.out.println(str.charAt(0));

        }

    }

}

@类型转换异常(ClassCastException)

public class Test5 {

    public static void main(String[] args) {

        Animal a = new Dog();

        if (a instanceof Cat) {

            Cat c = (Cat) a;

        }

    }

}

@数组下标越界异常(ArrayIndexOutOfBoundsException)//增加关于边界的判断

public class Test6 {

    public static void main(String[] args) {

        int[] arr = new int[5];

        int a = 5;

        if (a < arr.length) {

            System.out.println(arr[a]);

        }

    }

}

@数字格式异常(NumberFormatException)

在使用包装类将字符串转换成基本数据类型时,如果字符串的格式不正确

public class Test7 {

    public static void main(String[] args) {

        String str = "1234abcf";

        Pattern p = Pattern.compile("^\\d+$");

        Matcher m = p.matcher(str);

        if (m.matches()) { // 如果str匹配代表数字的正则表达式,才会转换

            System.out.println(Integer.parseInt(str));

        }

    }

}

5)CheckedException已检查异常

 所有不是RuntimeException的异常,统称为Checked Exception,又被称为“已检查异常”,如IOException、SQLException等以及用户自定义的Exception异常。 这类异常在编译时就必须做出处理,否则无法通过编译

注: 异常的处理方式有两种:使用“try/catch”捕获异常、使用“throws”声明异常

6)异常处理机制——捕获异常

@通过try-catch-finally来实现

###用try来执行一段程序,如果出现异常,系统抛出一个异常,可以通过它的类型来捕捉(catch)并处理它,最后一步是通过finally语句为异常处理提供一个统一的出口,finally所指定的代码都要被执行(catch语句可有多条;finally语句最多只能有一条,根据自己的需要可有可无)

###注意

 && 即使try和catch块中存在return语句,finally语句也会执行。是在执行完finally语句后再通过return退出。

 && finally语句块只有一种情况是不会执行的,那就是在执行finally之前遇到了System.exit(0)结束程序运行。

@ 声明异常:当CheckedException产生时,不一定立刻处理它,可以再把异常throws出去  

 ###方法重写中声明异常原则:子类重写父类方法时,如果父类方法有声明异常,那么子类声明的异常范围不能超过父类声明的范围。

7)手动抛出异常

@@如何使用:JDK提供的任何标准异常类都无法充分描述清楚我们想要表达的问题,这种情况下可以创建自己的异常类,即自定义异常类

@@自定义异常类如果继承Exception类,则为受检查异常,必须对其进行处理;如果不想处理,可以让自定义异常类继承运行时异常RuntimeException类

 @@习惯上,自定义异常类应该包含2个构造器:一个是默认的构造器,另一个是带有详细信息的构造器。

容器 (集合)

相比于数组更强大、更灵活、容量

1)泛型(可以帮助我们建立类型安全的集合。在使用了泛型的集合中,遍历时不必进行强制类型转换)

@声明

class MyCollection<E> {// E:表示泛型;字符可以是任何标识符,一般采用这3个字母<T,E,V>。

    Object[] objs = new Object[5];

    public E get(int index) {// E:表示泛型;

        return (E) objs[index];

    }

    public void set(E e, int index) {// E:表示泛型;

        objs[index] = e;

    }

}   //可以理解为一种数据类型

2)Collection接口

@@ Collection接口的两个子接口是List、Set接口,所有List、Set的实现类都有下面的方法

 @@list (有序、可重复的容器)

 ## 有序:List中每个元素都有索引标记。可以根据元素的索引标记(在List中的位置)访问元素,从而精确控制这些元素。

  ##可重复:List允许加入重复的元素。更确切地讲,List通常允许满足 e1.equals(e2) 的元素重复加入容器。

注意:除了Collection接口中的方法,List多了一些跟顺序(索引)有关的方法,参见下表:

使用方法:

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

        System.out.println(list.isEmpty()); // true,容器里面没有元素

        list.add("编程");

        System.out.println(list.isEmpty()); // false,容器里面有元素

 ##两个List之间的元素处理

##List中操作索引的常用方法

 

Map接口

##  Map就是用来存储“键(key)-值(value) 对”的。 Map类中存储的“键值对”通过键来标识,所以“键对象”不能重复。//重复与否是根据equals判断

 ###  Map 接口的实现类有HashMap、TreeMap、HashTable、Properties等。

 例子:

        m1.put(1"one");

        m1.put(2"two");

        m1.put(3"three");

        m2.put(1"一");

        m2.put(2"二");

        System.out.println(m1.size());

        System.out.println(m1.containsKey(1));

        System.out.println(m2.containsValue("two"));

        m1.put(3"third"); //键重复了,则会替换旧的键值对

 HashMap底层实现详解(结合了“数组+链表”的优点)

 1)数据结构中由数组和链表来实现对数据的存储

@@数组:占用空间连续。 寻址容易,查询速度快。但是,增加和删除效率非常低。

 @@链表:占用空间不连续。 寻址困难,查询速度慢。但是,增加和删除效率非常高。

2)存储数据:

 先 获得key对象的hashcode 再根据hashcode计算出hash值(要求在[0, 数组长度-1]区间)

 取数据过程

 (1) 获得key的hashcode,通过hash()散列算法得到hash值,进而定位到数组的位置。

 (2) 在链表上挨个比较key对象。 调用equals()方法,将key对象和链表上所有节点的key对象进行比较,直到碰到返回true的节点对象为止。

   (3) 返回equals()为true的节点对象的value对象。

 注:本篇文章部分图片来自尚学堂 JAVA 高淇 java 300 集大型基础课程_哔哩哔哩_bilibili

Protobuf是一种高效的序列化协议,可以用于数据交换和数据存储。它的主要优势是大小小,速度快,可扩展性强。下面是使用Protobuf的一些小记: 1. 定义消息格式 首先,需要定义消息格式,以便Protobuf可以将数据序列化和反序列化。消息格式定义在.proto文件中,使用protobuf语言编写。例如,下面是一个简单的消息格式定义: ``` syntax = "proto3"; message Person { string name = 1; int32 age = 2; } ``` 这个消息格式定义了一个名为Person的消息,包含两个字段:name和age。 2. 生成代码 一旦消息格式定义好,就可以使用Protobuf编译器生成代码。编译器将根据消息格式定义生成相应的代码,包括消息类、序列化和反序列化方法等。可以使用以下命令生成代码: ``` protoc --java_out=. message.proto ``` 这将生成一个名为message.pb.javaJava类,该类包含Person消息的定义以及相关方法。 3. 序列化和反序列化 一旦生成了代码,就可以使用Protobuf序列化和反序列化数据。例如,下面是一个示例代码,将一个Person对象序列化为字节数组,并将其反序列化为另一个Person对象: ``` Person person = Person.newBuilder() .setName("Alice") .setAge(25) .build(); byte[] bytes = person.toByteArray(); Person deserializedPerson = Person.parseFrom(bytes); ``` 这个示例代码创建了一个Person对象,将其序列化为字节数组,然后将其反序列化为另一个Person对象。在这个过程中,Protobuf使用生成的代码执行序列化和反序列化操作。 以上是使用Protobuf的一些基本步骤和注意事项,希望对你有所帮助!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值