ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Java基础实战:面向对象、String与异常处理核心讲解

Java基础实战:面向对象、String与异常处理核心讲解 做Java基础系列做到第三期我是有点感慨的。前两篇我们聊了Java环境搭建、基本语法、流程控制这些入门内容后台收到最多的留言不是语法看不懂而是语法都认识一写就废。尤其是很多人卡在面向对象、字符串、异常这几块觉得自己背了不少概念但真正写代码时根本不顺手一到面试问两句就露馅。这期Java基础03我就把这些核心内容掰开揉碎用实际开发中的场景来讲。不是给你堆概念而是让你看完就能写、写完能懂、懂了能应付面试。这期重点讲四个东西面向对象编程的落地理解、String与字符串处理的底层逻辑、异常处理机制、数组与排序算法的实战。这几个点几乎是所有Java面试题和日常工作的高频区把它们吃透你后面学集合、学框架会轻松很多。如果你正在自学Java、准备校招面试或者刚入职不久发现基础不牢这篇文章应该能帮你把地基补结实。文章里的代码我都实际跑过你直接照着敲一遍比看十遍理论都管用。1. 对象与类你的代码为什么总在面向过程很多初学者对面向对象四个字有天然的敬畏觉得这是很高深的东西。其实说白了面向对象就是把现实世界的事物映射到程序里。你写一个学生管理系统你关心的不是程序怎么跑而是学生这个对象有什么属性、能做什么事。属性就是字段能做的事就是方法就这么简单。1.1 类和对象的正确理解方式类是什么类就是模板是图纸。对象是什么对象是根据图纸造出来的实物。你用一张学生证模板类可以批量印发很多张具体的学生证对象每张上面名字、学号不同这就是同一个类可以创建多个对象而且每个对象的数据互不干扰。public class Student { // 字段描述对象的状态 private String name; private int age; // 构造方法创建对象时初始化 public Student(String name, int age) { this.name name; this.age age; } // 方法描述对象的行为 public void showInfo() { System.out.println(姓名 name 年龄 age); } }用的时候就这样Student s1 new Student(张三, 20); Student s2 new Student(李四, 22); s1.showInfo(); s2.showInfo();我在实际教学中发现很多新人最大的困惑点是this关键字。记住一句话谁调用方法this 就代表谁。你s1.showInfo()那 showInfo 方法里的 this 就是 s1。另外一个高频坑是忘了写构造方法程序报错找不到构造器。其实 Java 会默认提供一个无参构造方法但如果你自己写了一个带参构造方法默认的无参构造就会被覆盖。所以要么显式把无参构造写上要么就别只写带参的。这是面试里特别喜欢问的一点。1.2 封装、继承、多态在代码里到底怎么体现这三个词几乎是 Java 面试八股文的第一关但很多人背了定义却讲不出落地场景。先看封装。封装的意义不是把字段设为 private 就完事而是对外提供受控的访问入口。比如年龄你不能随便赋个负数在 setter 里做校验public void setAge(int age) { if (age 0 || age 150) { throw new IllegalArgumentException(年龄不合法); } this.age age; }有人觉得这不就是从 private 改成 public 加几行代码吗区别在于以后你需要在赋值时统一加逻辑只改一个方法就够了。不然你代码里一百处直接s.age 25每处都要找出来改那才是真正的灾难。再看继承。继承解决的是多个类有公共代码的问题。比如老师和学生都有姓名和年龄都吃饭那就搞一个 Person 父类Teacher 和 Student 继承它。public class Person { protected String name; protected int age; public void eat() { System.out.println(name 正在吃饭); } } public class Teacher extends Person { private String subject; public void teach() { System.out.println(name 正在教 subject); } }注意我用了protected它的意思是子类可以访问包内可以访问包外不行。这是实际开发中很常用、但初学者基本没概念的访问修饰符。多态就更有意思了。多态的核心是父类引用指向子类对象。比如你写一个系统今天需要老师对象明天可能需要学生对象但调用入口统一用 PersonPerson p new Teacher(王老师, 35); p.eat(); // 输出王老师正在吃饭但是要注意如果你用 Person 类型的引用调用 eat()哪怕 Teacher 重写了 eat()也只会执行子类的 eat()这就是动态绑定。如果你用 Person 引用去调 teach()编译直接报错因为编译器只看引用类型有没有这个方法。这个点面试必考很多人栽在这里。1.3 重载与重写的区别用代码讲清楚重载Overload是同一个类里方法名相同参数列表不同。重写Override是子类对父类的方法重新实现方法签名必须一模一样。重载典型例子public class Calculator { public int add(int a, int b) { return a b; } public double add(double a, double b) { return a b; } }重写典型例子public class Animal { public void speak() { System.out.println(动物叫); } } public class Dog extends Animal { Override public void speak() { System.out.println(汪汪汪); } }我建议你写代码时一定加Override注解。这个注解不写程序也能跑但写了之后如果你方法签名写错了比如参数类型不匹配编译器会第一时间告诉你这不是重写能救命。这也是面试官考察你有没有实际项目经验的细节点之一。2. String 与字符串处理你最熟悉也最陌生的类String 是 Java 里最常用的类没有之一。但恰恰因为太常用很多人对它的底层机制一知半解。面试题里关于 String 的坑特别多这里我把高频考点全部讲透。2.1 字符串常量池与到底比较的是什么先看这段代码String a hello; String b hello; String c new String(hello); System.out.println(a b); // true System.out.println(a c); // false System.out.println(a.equals(c)); // true很多人不理解为什么前两个 true 后一个是 false。这就要说到字符串常量池。用字面量hello创建字符串时JVM 会先检查常量池里有没有这个值有就直接复用没有就创建一个放进去。所以 a 和 b 指向的是同一个对象比较的是内存地址自然 true。而new String(hello)是强制在堆内存里创建一个新对象地址完全不同所以 a c 是 false。equals 比较的是内容所以是 true。这里需要知道一个更大的坑字符串拼接。看下面的代码String s1 hello; String s2 s1 world;只要字符串拼接中有变量参与JVM 实际会创建一个新的 StringBuilder 对象来拼接最终结果存放在堆内存不是常量池。如果你拿s2 hello world去比较结果是 false。面试里问字符串比较的题十有八九是围绕这个展开的。2.2 String、StringBuilder、StringBuffer 怎么选我见过很多新手用 String 做大量拼接在循环里写了几万次str xxx结果程序卡到怀疑人生。原因是 String 是不可变对象每一次拼接都会创建一个新字符串对象循环一万次就创建一万个对象扛不住。StringBuilder 和 StringBuffer 都是可变字符序列区别在于 StringBuffer 的方法用 synchronized 修饰线程安全但性能略低。绝大多数场景下你用 StringBuilder 就够了。不用纠结单线程环境直接 StringBuilder不要犹豫。实际项目中最常见的写法是这样的StringBuilder sb new StringBuilder(); for (int i 0; i 1000; i) { sb.append(第).append(i).append(条数据\n); } String result sb.toString();这样只创建一个 StringBuilder 对象性能差距是数量级的。你可以自己写段代码计时测试循环一千万次拼接用 String 和 StringBuilder 分别跑感受一下什么叫肉眼可见的卡顿。2.3 高频字符串操作技巧手动处理字符串是每天都要做的事。我挑几个最常用、也最容易出错的点说。split分割时有个隐藏陷阱如果字符串末尾有分隔符split 会默认丢弃末尾的空字符串。比如a,b,,c,.split(,)你拿到的是[a, b, , c]最后一个空串被丢了。需要保留的话用split(,, -1)。substring的端点是左闭右开。hello.substring(1, 3)的结果是el不是ell。这个记错了会直接在业务逻辑上出 bug。equals和equalsIgnoreCase要区别用。写登录校验时用户输入验证码一般就用 equalsIgnoreCase 忽略大小写。但是在金融项目里比较订单号、交易流水号别乱忽略大小写必须用 equals。还有个实用技巧判断字符串是否为空用第三方工具库的StringUtils.isBlank()比手写str null || str.isEmpty()更稳妥因为它连全角空格、制表符这些都能识别。工作里你大概率会用 Hutool 或 Apache Commons Lang这是基本功。3. 异常处理别再吞异常了真的会出事异常处理这块很多自学的人容易忽略觉得程序正常跑通就够了。但实际工作中异常处理写得好不好直接决定项目上线后你半夜会不会被电话叫醒。3.1 异常体系结构理清三个家族的级别Java 的异常体系大致分三层Throwable 是所有异常的父类下面分 Error 和 Exception。Error 是 JVM 层面的严重问题比如 OutOfMemoryError、StackOverflowError。这些你处理不了也不该处理程序直接崩了就崩了。我见过新手写代码 catch Exception 去捕获内存溢出这是没意义的。Exception 又分为受检异常Checked Exception和运行时异常RuntimeException。受检异常是编译器强制让你处理的比如 IOException、SQLException。你不处理代码编译不过。运行时异常则不需要强制处理比如 NullPointerException、ArithmeticException、ArrayIndexOutOfBoundsException。记住一个观点受检异常用 try-catch 或 throws 处理运行时异常主要用于程序逻辑错误的防护参考 console 报错定位问题。面试官如果让你列举常见的运行时异常你说出 NPE空指针、数组越界、类型转换异常、算术异常这几个就够了但最好能带一句这些大多是可以通过代码逻辑避免的。3.2 try-catch-finally 的正确打开方式try-catch-finally 看着简单但很多人写错了。核心注意点有三个。第一catch 分支从上到下子类异常必须写在父类异常前面否则编译器直接报错。比如要同时
返回列表