前言:细节决定成败,希望自己早日改掉坏习惯,脑子不要老是一团浆糊!!!
1、交换失败
public static void swap(int a, int b){
int t=a;
a=b;
b=t;
}
原因:Java 是按值传递的,方法参数传递的是值的拷贝,对于基本数据类型(如 int)传递的是值的副本,所以在方法内部交换 a
和 b
的值并不会影响到原始的值。正确方法:
public static void swap(int[] arr, int i, int j)
2、char和String的符号
' '用于char," "用于String
3、求长度
数组:arr.length,字符串:str.length(),注意括号
4、==
和equals
==操作符:在基本数据类型比较时,==
用于比较它们的值是否相等。在引用类型比较时,==
用于比较两个对象的引用(即对象在内存中的地址)是否相同,即判断两个对象是否是同一个对象。如果两个引用指向的是内存中的同一块区域,则返回 true
,否则返回 false
。
equals
方法:equals
方法是用于比较对象之间的内容是否相等,需要由对象的类实现(通常是覆盖 Object
类中的 equals
方法)。在一些 Java 类库中,equals
方法被覆盖以实现对对象内容的比较,例如 String
、Integer
等类都覆盖了 equals
方法。
String str1 = new String("Hello");
String str2 = new String("Hello");
String str3 = str1;
System.out.println(str1 == str2); // 输出 false,因为它们是不同的对象
System.out.println(str1 == str3); // 输出 true,因为它们引用的是同一个对象
System.out.println(str1.equals(str2)); // 输出 true,因为它们的内容相等
5、面向对象三大特征
封装:它将数据和操作这些数据的方法打包在一起,形成一个独立的、自包含的单元——类。通过封装,对象内部的实现细节被隐藏起来,外部代码只能通过对象提供的接口(方法)来访问数据,从而实现了数据的安全性和隔离性。
继承:它允许一个类(子类)基于另一个类(父类)的属性和方法来进行扩展。子类继承了父类的特性,可以重用父类的代码,并且可以在不修改父类的情况下,通过添加新的功能或修改现有功能来满足特定需求。
多态:多态性是指同一个方法调用在不同的对象上可以有不同的行为。多态允许子类对父类的方法进行重写,使得不同对象可以以自己的方式响应相同的消息或调用相同的方法,这意味着同一个类型的对象在执行同一个方法时可能表现出多种行为特征。通过多态性,可以提高代码的灵活性和可扩展性。
6、面向对象七大设计原则
6.1、开闭原则(Open-Closed Principle, OCP),指软件实体(类、模块、方法等)应该对扩展开放,对修改关闭。这意味着设计时应该易于扩展,添加新功能时,尽量不修改现有代码,而是通过添加新代码来实现。
6.2、 单一职责原则(Single Responsibility Principle, SRP),指一个类应该只有一个引起它变化的原因,即一个类只负责一项职责。这样做的目的是使类更加清晰,更容易理解和维护。
6.3、接口隔离原则(Interface Segregation Principle, ISP),指客户端不应该依赖它不需要的接口。这意味着设计接口时应该尽量精简,不应该设计臃肿庞大的接口。
6.4、依赖倒置原则(Dependency Inversion Principle, DIP),指高层模块不应该依赖低层模块,二者都应该依赖其抽象;抽象不应该依赖细节,细节应该依赖抽象。这意味着设计时应该尽量依赖接口或抽象类,而不是实现类。
6.5、里氏代换原则(Liskov Substitution Principle, LSP),指所有引用基类的地方必须能透明地使用其派生类的对象。即任何父类可以出现的地方,子类也一定可以出现。
6.6、迪米特原则(Law of Demeter, LoD)又叫最少知道原则(Least Knowledge Principle),指一个软件实体应当尽可能少地与其他实体发生相互作用;每一个软件单位对其他的单位都只有最少的知识,而且局限于那些与本单位密切相关的软件单位。
6.7、组合/聚合复用原则(Composite/Aggregate Reuse Principle , CARP),指尽量使用组合/聚合,不要使用类继承。
7、权限修饰符
权限修饰符可以用于类的成员变量、方法、构造函数等,用来控制不同类成员的访问范围,确保代码的封装性和安全性。
-
public
:表示公共访问权限,被修饰的成员可以在任何地方被访问。即使是不同包中的类,只要它们能够访问该类,就可以访问该成员。 -
protected
:表示受保护访问权限,被修饰的成员可以被同一包中的类以及该类的子类访问。不同包中的类只能通过继承该类来访问受保护成员。 -
default
(不写任何修饰符):表示默认访问权限,即包级访问权限。被修饰的成员可以在同一包中被访问,但是在不同包中无法访问。 -
private
:表示私有访问权限,被修饰的成员只能在定义该成员的类中访问,其他任何类都无法访问私有成员。
8、父子类初始化顺序
9、ArrayList遍历问题
for (int i = 0; i < array.size(); i++) {
if (array.get(i).time <= time) {
Task t = array.remove(i);
res[t.job] = time;
}
}
删除操作会有两个问题:数组大小变化:每次移除元素后,array.size()
会减小。索引偏移:当元素被移除后,arr
ay中的元素会左移,后续的元素会占据被移除元素的位置。这使得后续的元素的索引发生了变化。
解决方案:从后向前遍历
从数组的末尾向前遍历,这样移除元素不会影响未遍历部分的索引。
for (int i = array.size() - 1; i >= 0; i--) {
if (array.get(i).time <= time) {
Task t = array.remove(i);
res[t.job] = time;
}
}
10、接口默认方法
// 定义一个接口,包含一个默认方法
public interface MyInterface {
default void display() {
System.out.println("This is the default implementation.");
}
}
如果一个类实现了这样一个包含默认方法的接口,那么它可以:
直接继承接口中的默认方法实现,无需提供自己的实现。
重写接口中的默认方法,提供自己的实现。(重写时最好使用@Override注解,防止默认方法改变时受到影响)
11、自增/自减问题
int i = 1;
i = i++;
System.out.println(i);
// 输出2? No No No,输出1
对于 JVM 而言,它对自增运算的处理,是会先定义一个临时变量来接收 i 的值,然后进行自增运算,最后又将临时变量赋给了值为 2 的 i,所以最后的结果为 1。相当于:
int i = 1;
int temp = i;
i++; // i=2
i = temp; // i=1
System.out.println(i);