Java学习笔记
更新: 2024/7/29 字数: 0 字 时长: 0 分钟
前言
NOTE
强调用户在快速浏览文档时也不应忽略的重要信息。
此学习文档由whisper
一起制作完成
Java基础
我们简单学习一遍基础知识
Hello World 程序
这是一个简单的Java程序,它会输出"Hello, World!"
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello, World!");
}
}
变量和数据类型
Java有多种数据类型,如整型、浮点型、字符型和布尔型
public class Variables {
public static void main(String[] args) {
int myInt = 5;
double myDouble = 5.99;
char myChar = 'A';
boolean myBool = true;
String myString = "Hello";
System.out.println(myInt);
System.out.println(myDouble);
System.out.println(myChar);
System.out.println(myBool);
System.out.println(myString);
}
}
条件语句
Java中的条件语句包括if
、else if
和else
public class Conditional {
public static void main(String[] args) {
int x = 10;
if (x < 20) {
System.out.println("x 小于 20");
} else if (x == 20) {
System.out.println("x 等于 20");
} else {
System.out.println("x 大于 20");
}
}
}
循环语句
Java中的循环语句包括for
、while
和do-while
public class Loops {
public static void main(String[] args) {
// for loop
for (int i = 0; i < 5; i++) {
System.out.println("for loop: i = " + i);
}
// while loop
int j = 0;
while (j < 5) {
System.out.println("while loop: j = " + j);
j++;
}
// do-while loop
int k = 0;
do {
System.out.println("do-while loop: k = " + k);
k++;
} while (k < 5);
}
}
数组
数组是存储相同数据类型元素的集合
public class Arrays {
public static void main(String[] args) {
int[] myArray = {1, 2, 3, 4, 5};
for (int i = 0; i < myArray.length; i++) {
System.out.println("Element at index " + i + ": " + myArray[i]);
}
}
}
方法
方法是执行特定任务的代码块
public class Methods {
public static void main(String[] args) {
int result = add(5, 3);
System.out.println("5 + 3 = " + result);
}
public static int add(int a, int b) {
return a + b;
}
}
类与对象
面向对象的概念
面向对象是让多个对象合作最后完成目的
类和对象
- 类是对具有相同特征的对象的一个抽象
- 对象是对一个类的具体化(实例化)
//Dog类
public class Dog {
//编写的属性
String name;
int age;
public Dog(String name, int age) {
this.name = name;
this.age = age;
}
//编写的方法
public void bark() {
System.out.println(name + " is barking!");
}
public static void main(String[] args) {
//创建对象
Dog myDog = new Dog("Buddy", 3);
//访问方法语法格式
myDog.bark();
}
}
封装(Encapsulation)
类的封装作用
封装是将对象的属性(字段)和行为(方法)结合起来,并隐藏对象的内部实现细节,只对外暴露必要的接口,这样可以保护数据不被外部随意修改
类定义以及属性的封装
private String name;
private int age;
get/set方法
赋值方法:set
方法
//无返回值类型
public void setName(String name) {
this.name = name;
}
取值方法:get
方法
//有返回值类型
public String getName() {
return name;
}
构造方法的定义和特点
- 构造方法名称和类型保持一致
- 没有返回值类型
- 没有具体的返回值
this关键字
出现局部变量和成员变量同名时使用
public void setName(String name) {
//局部变量,左右相等,赋值失败
name = name;
}
public void setName(String name) {
//name1局部变量,name成员变量
name = name1;
}
public void setName(String name) {
//this代表调用set方法的变量
this.name = name;
}
示例代码:
public class Person {
// 属性的封装
private String name;
private int age;
public Person(){
}
// 公共构造方法
public Person(String name, int age) {
this.name = name;
this.age = age;
}
// 公共方法来访问私有字段
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
if (age > 0) {
this.age = age;
} else {
System.out.println("Age must be positive.");
}
}
// 一个示例方法
public void displayInfo() {
System.out.println("Name: " + name + ", Age: " + age);
}
}
关键点:
- 使用
private
关键字将属性私有化 - 通过公共的
getter
和setter
方法来访问和修改私有属性
继承(Inheritance)
继承的作用
继承是Java中用于建立新类与现有类之间的关系的机制
新类(子类)可以继承现有类(父类)的属性和方法,并可以添加新的属性和方法或重写父类的方法,提高了代码的复用性
继承书写方式
包括子类如何访问父类的变量、方法和构造方法
1、继承的使用
extends
关键字只支持单继承不支持多继承
2、子父类的成员变量、成员方法、构造方法的特点
成员变量
- 子类访问父类的成员变量:
super
关键字
成员方法
- 先在子类找,再去父类
- 子类和父类一样时,覆盖操作
- 重写时权限大于父类权限
- 和父类方法声明、返回值类型、方法名、参数列表都一样
构造方法
- 父类没有空参构造,子类要写
super
语句 - 子类第一行默认隐式
super()
语句
示例代码:
// 父类
public class Animal {
protected String name;
public Animal(String name) {
this.name = name;
}
public void eat() {
System.out.println(name + " is eating.");
}
}
// 子类
public class Dog extends Animal {
public Dog(String name) {
super(name);
}
public void bark() {
System.out.println(name + " is barking.");
}
// 重写父类的方法
@Override
public void eat() {
System.out.println(name + " is eating dog food.");
}
}
关键点:
- 使用
extends
关键字来声明继承关系 - 子类可以重写父类的方法(使用
@Override
注解) - 子类可以调用父类的构造方法(使用
super
关键字)
多态(Polymorphism)
多态允许同一个方法在不同对象中有不同的实现
它有两种形式:编译时多态(方法重载)和运行时多态(方法重写)
多态的三个前提
- 继承/实现接口
- 方法重写
- 父类引用指向子类对象
多态转型
向上转型
默认向上转型
向下转型
字类类型 变量名 = (子类类型)父类类型变量
多态访问子类独有方法容易出现异常,所以需要用instanceof判断类型
//课本p56 例题
class Work{
String name;
int age;
public Work(String name,int age){
this.name = name;
this.age = age;
}
}
class Manager extends Work{
public Manager(String name,int age){
super(name,age)
}
}
class Boss extends Worker{
public Manager(String name,int age){
super(name,age)
}
}
public class Demo4{
public static void main(String []args){
Work [] workers = { new Manager("经理1",20),new Boss("老板1",35) ;
for(int i = 0 ;i<workers.length;i++){
if(workers[i] instanceof Manager){
Manager manager = (Manager) Workers[i];
}else if(workers[i] instanceof Boss[i]){
Manager manager = (Manager) boss[i];
}else{
System.out.println("程序错误")
}
}
}
}
多态的弊端和解决
多态的弊端主要包括:
- 性能开销:多态通常通过虚函数表(vtable)实现,调用虚函数时需要通过虚表指针查找函数地址,增加了运行时开销
- 调试困难:由于多态使得对象的实际类型在运行时才确定,调试和排查错误变得更加复杂
- 内存开销:支持多态的类通常需要额外的内存来存储虚函数表指针
- 维护复杂:多态依赖于继承层次结构,随着项目规模的扩大,继承层次变得复杂,维护难度增加
解决多态弊端的方法:
- 静态多态:使用模板和编译时多态(如CRTP)来替代运行时多态,减少虚函数调用的开销
- 减少继承层次:尽量简化继承层次,减少层级,提高代码的可维护性
- 组合优于继承:使用组合模式而不是继承来实现对象行为的复用和扩展
- 优化虚函数调用:对于性能关键的部分,尽量避免频繁的虚函数调用,可以通过内联函数、函数指针等方式进行优化
通过这些方法,可以在一定程度上减小多态带来的弊端,提高代码的性能和可维护性
示例代码:
多态的语法
// 方法重载(编译时多态)
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 makeSound() {
System.out.println("Animal is making a sound");
}
}
public class Dog extends Animal {
@Override
public void makeSound() {
System.out.println("Dog is barking");
}
}
public class Cat extends Animal {
@Override
public void makeSound() {
System.out.println("Cat is meowing");
}
}
// 演示多态
public class Main {
public static void main(String[] args) {
Animal myAnimal = new Animal(); // Animal 对象
Animal myDog = new Dog(); // Dog 对象
Animal myCat = new Cat(); // Cat 对象
myAnimal.makeSound(); // 输出:Animal is making a sound
myDog.makeSound(); // 输出:Dog is barking
myCat.makeSound(); // 输出:Cat is meowing
}
}
关键点:
- 方法重载:同一个类中,同名方法可以有不同的参数列表
- 方法重写:子类可以提供父类方法的具体实现
- 多态行为:父类引用可以指向子类对象,调用方法时会根据对象的实际类型执行相应的方法
抽象类(Abstract Class)
定义和特点
抽象类是不能被实例化的类,可以包含抽象方法和非抽象方法
抽象方法没有方法体,必须在子类中实现
示例代码:
// 抽象类
abstract class Animal {
// 抽象方法
public abstract void makeSound();
// 非抽象方法
public void sleep() {
System.out.println("Sleeping...");
}
}
// 子类必须实现抽象方法
class Dog extends Animal {
@Override
public void makeSound() {
System.out.println("Dog barks");
}
}
接口(Interface)
定义和特点
接口是一种特殊的类,所有方法都是抽象方法
类通过implements
关键字实现接口,可以实现多个接口
示例代码:
// 接口
interface Animal {
void makeSound();
}
// 实现接口的类
class Dog implements Animal {
@Override
public void makeSound() {
System.out.println("Dog barks");
}
}
类的高级特性
静态成员(Static Members)
静态成员属于类而不是实例,可以通过类名直接访问
class MyClass {
static int staticVariable = 5;
static void staticMethod() {
System.out.println("Static method called");
}
}
// 访问静态成员
MyClass.staticMethod();
int value = MyClass.staticVariable;
内部类(Inner Classes)
内部类是定义在另一个类中的类,有助于组织代码
示例代码:
class OuterClass {
private int x = 10;
class InnerClass {
public void display() {
System.out.println("x = " + x);
}
}
}
// 使用内部类
OuterClass outer = new OuterClass();
OuterClass.InnerClass inner = outer.new InnerClass();
inner.display();
反射(Reflection)
反射允许在运行时检查和操作类和对象
示例代码:
import java.lang.reflect.Method;
class MyClass {
public void myMethod() {
System.out.println("myMethod called");
}
}
public class ReflectionDemo {
public static void main(String[] args) throws Exception {
Class<?> clazz = Class.forName("MyClass");
Method method = clazz.getMethod("myMethod");
Object obj = clazz.newInstance();
method.invoke(obj);
}
}
异常(Exceptions)
异常的体系结构
- 抛出异常
- throw关键字:用于显式抛出一个异常对象
if (condition) {
throw new IllegalArgumentException("Invalid argument");
}
- throws关键字:用于方法声明,表示该方法可能抛出某种异常
public void readFile(String filePath) throws IOException {
// method implementation
}
- 捕获异常
- try-catch语句:用于捕获并处理异常
try {
// code that may throw an exception
} catch (ExceptionType1 e1) {
// handle ExceptionType1
} catch (ExceptionType2 e2) {
// handle ExceptionType2
} finally {
// cleanup code, always executed
}
- finally块:无论是否发生异常,
finally
块中的代码总是会执行,用于释放资源
try {
// code that may throw an exception
} catch (Exception e) {
// handle exception
} finally {
// cleanup code
}
- 自定义异常
- 定义自定义异常类:继承
Exception
或RuntimeException
public class CustomException extends Exception {
public CustomException(String message) {
super(message);
}
}
- 抛出和捕获自定义异常:
public void someMethod() throws CustomException {
if (condition) {
throw new CustomException("Custom error message");
}
}
try {
someMethod();
} catch (CustomException e) {
// handle custom exception
}
- 常见异常处理模式
- 资源关闭模式:使用
try-with-resources
语句,确保资源关闭
try (BufferedReader br = new BufferedReader(new FileReader("file.txt"))) {
// use the resource
} catch (IOException e) {
// handle exception
}
- 日志记录模式:捕获异常后记录日志,方便调试和维护
try {
// code that may throw an exception
} catch (Exception e) {
logger.error("An error occurred", e);
}
- 重抛异常:在
catch
块中捕获异常后,重新抛出,传递给调用者处理
try {
// code that may throw an exception
} catch (Exception e) {
throw e;
}
5.异常处理的最佳实践
- 避免吞掉异常:不要在
catch
块中不做任何处理 - 使用具体的异常类型:在
catch
块中捕获具体的异常类型,而不是笼统的Exception - 抛出有意义的异常:抛出异常时,提供详细的错误信息,便于调试和维护
- 清理资源:在
finally
块中或使用try-with-resources
语句,确保资源被正确关闭
Java常用类
字符串(String)
String str = "Hello, World!";
int length = str.length();
String upperStr = str.toUpperCase();
日期和时间(Date and Time)
import java.time.LocalDate;
import java.time.LocalTime;
import java.time.LocalDateTime;
LocalDate date = LocalDate.now();
LocalTime time = LocalTime.now();
LocalDateTime dateTime = LocalDateTime.now();
集合(Collections)
List接口
import java.util.ArrayList;
import java.util.List;
List<String> list = new ArrayList<>();
list.add("apple");
list.add("banana");
System.out.println(list.get(0)); // 输出: apple
Map集合
import java.util.HashMap;
import java.util.Map;
Map<String, Integer> map = new HashMap<>();
map.put("apple", 1);
map.put("banana", 2);
System.out.println(map.get("apple")); // 输出: 1
IO流(Input/Output Streams)
文件读取
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
try (BufferedReader br = new BufferedReader(new FileReader("file.txt"))) {
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
文件写入
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
try (BufferedWriter bw = new BufferedWriter(new FileWriter("file.txt"))) {
bw.write("Hello, World!");
} catch (IOException e) {
e.printStackTrace();
}
多线程(Multithreading)
创建线程
// 继承Thread类
class MyThread extends Thread {
@Override
public void run() {
System.out.println("Thread is running");
}
}
MyThread thread = new MyThread();
thread.start();
// 实现Runnable接口
class MyRunnable implements Runnable {
@Override
public void run() {
System.out.println("Runnable is running");
}
}
Thread thread = new Thread(new MyRunnable());
thread.start();
JDBC(Java Database Connectivity)
用于连接和操作数据库
示例代码:
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
public class JDBCDemo {
public static void main(String[] args) {
String url = "jdbc:mysql://localhost:3306/mydatabase";
String user = "root";
String password = "password";
try (Connection con = DriverManager.getConnection(url, user, password);
Statement stmt = con.createStatement()) {
String query = "SELECT * FROM users";
ResultSet rs = stmt.executeQuery(query);
while (rs.next()) {
System.out.println(rs.getString("username"));
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
如果你发现这篇指南有用,或者有改进建议,请随时联系我们或参与讨论。🎉 🎉 🎉