如何在Java中创建Immutable类?

Immutable类意味着一旦创建了一个对象,我们就无法改变它的内容。在Java的中,所有包装类(如字符串,布尔值,字节,短)和字符串类都是不可变的。我们也可以创建自己的不可变类。

以下是要求:

•必须将类声明为最终(因此无法创建子类)

•必须将类中的数据成员声明为最终(因此在创建对象后我们无法更改它的值)

•参数化构造函数

•其中所有变量的吸气方法

•无二传手(无法更改实例变量的值)

创建不可变类的示例

// immutable class 
public final class Student 
{ 
final String name; 
final int regNo; 
 
public Student(String name,int regNo)
{ 
this.name = name; 
this.regNo = regNo; 
} 
公共字符串的getName()
{ 
返回名字; 
} 
公众诠释getRegNo()
{ 
返回REGNO; 
} 
} 
 
//驱动程序类
类Test 
{ 
public static void main(String args [])
{ 
Student s = new Student(“ABC”,101); 
的System.out.println(s.getName()); 
的System.out.println(s.getRegNo()); 
 
//取消下面一行的注释会导致错误
// s.regNo = 102;
} 
}
输出:

ABC 
101

在这个例子中,我们创建了一个名为学生的最终类。它有两个最终数据成员,一个参数化构造函数和吸气方法。请注意,这里没有二传手方法。

(为了使其正常工作,在主函数中创建的学生类的对象。)

面试题及答案的获取方式,欢迎加入Java进阶架构交流群:142019080。

直接点击链接加群。https://jq.qq.com/?_wv=1027&k=5lXBNZ7

<think>嗯,用户之前问了函数式编程的概念,现在他们想知道在Java中如何理解这个概念。首先,我需要回忆一下Java中支持函数式编程的特性,尤其是Java 8引入的那些,比如Lambda表达式和Stream API。用户可能已经了解其他语言中的函数式编程,比如JavaScript的例子,所以需要将概念对应到Java的具体实现上。 接下来,用户可能想知道如何在Java中应用函数式编程的核心原则,比如纯函数、不可变数据、高阶函数等。我需要解释Java中的函数式接口,例如Function、Predicate、Consumer等,以及如何使用Stream API来替代传统的循环和命令式代码。 另外,用户可能对Java中的不可变性有疑问,比如如何创建不可变对象,使用final关键字,或者利用Collections.unmodifiable方法。需要提供具体的代码示例,说明如何在Java中实现数据不可变。 还需要提到Java的函数式编程限制,比如Java本质上还是面向对象的语言,函数式编程的支持并不像Haskell或Scala那样全面。但Java 8之后的改进确实让函数式风格成为可能,尤其是在集合处理和并行操作方面。 用户可能想知道为什么要在Java中使用函数式编程,比如代码简洁、易于并行处理、提高可读性等好处。同时,也可能需要指出一些注意事项,比如避免副作用,正确使用Stream API的终止操作等。 最后,应该给出一些实际的例子,比如用Stream的map、filter、reduce来替代传统循环,展示如何将之前的JavaScript示例转化为Java代码。这样用户可以通过对比更好地理解如何在Java中应用函数式编程。</think>--- ### Java 中的函数式编程核心实现: Java 从 **Java 8** 开始通过 **Lambda 表达式**、**函数式接口**和 **Stream API** 支持函数式编程,其核心设计围绕以下特性: --- #### 1. **函数式接口(Functional Interface)** - **定义**:只有一个抽象方法的接口(如 `Runnable`, `Comparator`) - **关键注解**:`@FunctionalInterface`(编译器强制检查) - **四大内置函数式接口**: ```java // 1. 有输入和输出(似数学函数) Function<T, R> → R apply(T t); // 例如:String转Integer // 2. 条件判断(返回布尔值) Predicate<T> → boolean test(T t); // 例如:筛选数字>10 // 3. 消费数据(无返回值) Consumer<T> → void accept(T t); // 例如:打印日志 // 4. 生产数据(无输入) Supplier<T> → T get(); // 例如:生成随机数 ``` **示例**:自定义函数式接口 ```java @FunctionalInterface interface StringProcessor { String process(String input); } // 使用Lambda实现 StringProcessor toUpper = s -> s.toUpperCase(); System.out.println(toUpper.process("hello")); // 输出 "HELLO" ``` --- #### 2. **Lambda 表达式** - **本质**:简化函数式接口的匿名内部写法 - **语法**:`(参数) -> { 代码块 }`(单行代码可省略 `{}` 和 `return`) - **型推断**:编译器根据上下文自动识别型 **对比传统写法**: ```java // 旧方式(匿名内部) new Thread(new Runnable() { @Override public void run() { System.out.println("Hello"); } }).start(); // Lambda表达式 new Thread(() -> System.out.println("Hello")).start(); ``` --- #### 3. **Stream API(核心工具)** - **特点**:链式调用、延迟执行、内部迭代 - **操作分**: - **中间操作**(Intermediate):`filter`, `map`, `sorted`, `distinct`(返回新Stream,可链式调用) - **终止操作**(Terminal):`collect`, `forEach`, `reduce`, `count`(触发实际计算) **典型场景**:集合处理 ```java List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5); // 函数式风格:筛选偶数 → 平方 → 求和 int sum = numbers.stream() .filter(n -> n % 2 == 0) // Predicate .map(n -> n * n) // Function .reduce(0, Integer::sum); // 终止操作 System.out.println(sum); // 输出 2² + 4² = 20 ``` --- ### Java 函数式编程的三大实践原则: #### 1. **用 Stream 替代循环** - **传统命令式代码**: ```java List<String> upperNames = new ArrayList<>(); for (String name : names) { if (name.startsWith("A")) { upperNames.add(name.toUpperCase()); } } ``` - **函数式重构**: ```java List<String> upperNames = names.stream() .filter(name -> name.startsWith("A")) .map(String::toUpperCase) .collect(Collectors.toList()); ``` --- #### 2. **强调不可变性(Immutable)** - **用 `final` 修饰变量**: ```java final List<Integer> list = Arrays.asList(1, 2, 3); // list = new ArrayList<>(); // 编译报错(引用不可变) ``` - **返回不可修改集合**: ```java List<Integer> unmodifiableList = Collections.unmodifiableList(list); // unmodifiableList.add(4); // 运行时抛出 UnsupportedOperationException ``` --- #### 3. **方法引用(:: 操作符)** - **进一步简化 Lambda**,直接引用已有方法: ```java // 静态方法引用 Function<String, Integer> parser = Integer::parseInt; // 实例方法引用 List<String> names = Arrays.asList("Bob", "Alice"); names.forEach(System.out::println); // 等价于 s -> System.out.println(s) // 构造方法引用 Supplier<List<String>> listSupplier = ArrayList::new; ``` --- ### Java 函数式编程的局限性: 1. **非纯粹的函数式语言**: - 无法完全避免副作用(如IO操作、异常处理) - 数据不可变性需要开发者主动维护(不像Haskell语言强制约束) 2. **性能取舍**: - Stream API 在简单场景可能比传统循环稍慢(但并行流可弥补) --- ### 快速应用建议: 1. **优先使用 Stream 处理集合**(替代 `for`/`while` 循环) 2. **多用 `final` 修饰变量**,减少可变状态 3. **组合函数式接口**: ```java // 组合 Predicate:筛选大于10且是偶数的数字 Predicate<Integer> isEven = n -> n % 2 == 0; Predicate<Integer> greaterThan10 = n -> n > 10; numbers.stream().filter(isEven.and(greaterThan10)); ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值