一.变量
(1)Kotlin的变量关键字
由于类型推导机制,Kolin的变量只有val(不可变)与var(可变),无需再声明类型。
val对应着Java的final关键字,因此定义变量时应优先考虑val。
(2)Java的变量命名规范
1. 全局变量:命名以m开头,随后单词首字母大写,例如:mHeartRate
2. 局部变量:命名以第二个单词开始首字母大写,例如:timeStatus
3. 静态变量:命名以s开头,随后单词首字母大写,例如:sScreenResolution
4. final关键字常量: 命名采用所有字母大写,单词直接用下划线隔开,例如:MAX_VALUE
(3)输入输出
Java打印信息采用System.out.printlin()方法
System.out.printlin("字符串" + 变量);
Java获取控制台输出有3种常用方法:
1. System.in.read()方法 2. BufferedReader类 3. Scanner类
其中,Scanner类在通过new Scanner(System.in)创建对象时,控制台会一直等待输入直到按回车键结束。
用户可通过next方法获取输入内容,常用的包括nextLine(),nextInt(),nextFloat(),nextBoolean()
Scanner scan = new Scanner(System.in);
String readInt = scan.nextInt();
System.out.printlin("输入数据:" + readInt);
二.函数与方法
(1)定义
Java中的方法,相当于C语言中的函数,不同点在于:
1.结构化语言中,程序由函数组成,函数可独立存在;
2.面向对象语言中,程序由类组成,方法不可独立存在,只能属于类或者对象。因此,定义一个方法时,必须在类中定义,如果方法不添加修饰符static,则方法属于这个类的实例,反之则属于这个类。
(2)关于Java的Static关键词
在 Java 中,通常情况下,如果方法需要访问对象的状态、需要被子类重写、或需要访问其他实例变量或方法,则应该将该方法定义为实例方法,而不使用 static 修饰符。
1. 实例方法: 如果方法需要访问对象的状态或操作对象的实例变量,则应该将该方法定义为实例方法,而不是静态方法。实例方法在每个对象实例上运行,因此它们通常与特定对象的状态相关联。
2. 需要被子类重写的方法: 如果希望子类能够重写方法,并根据子类的实现来调用方法,则应该将方法定义为实例方法而不是静态方法。静态方法不能被子类重写。
3. 需要访问实例变量或方法的方法: 如果方法需要访问实例变量或调用其他实例方法,则应该将该方法定义为实例方法,以便可以通过对象实例来访问它。
Java 中引入了 static 关键字主要是为了实现类级别的成员,使得这些成员不依赖于特定的对象实例而存在。这样做有以下几个好处:
1. 全局访问: 使用 static 关键字定义的成员可以直接通过类名访问,无需创建类的实例。这样可以方便地在不创建对象的情况下访问和调用这些成员,提高了代码的可读性和简洁性。
2. 共享状态: static 成员被所有类的实例所共享,可以用于保存全局状态或共享数据,比如常量、工具方法等。
3. 工具类和常量类: static 方法和字段经常被用于定义工具类和常量类,这样的类不需要被实例化,直接使用其中的方法和字段即可。
4. 性能优化: 静态方法和字段的调用比实例方法和字段更快,因为不需要额外的实例化过程和内存分配。
Static 还有以下一些常见的用途:
1. 常量定义: 在 Java 中,常量通常使用 static final 关键字组合来定义,以表示这是一个类级别的常量,无需实例化对象即可访问。
public class Constants {
public static final int MAX_COUNT = 100;
}
2. 工具类和常用方法: static 方法常被用于定义工具类和常用方法,这些方法无需创建对象实例就可以直接调用,例如 Math 类中的 sqrt() 方法。
public class MathUtils {
public static double squareRoot(double x) {
return Math.sqrt(x);
}
}
3. 单例模式: 使用 static 可以实现单例模式中的静态字段和静态方法,确保只有一个实例被创建并且在整个应用程序中可用。
public class Singleton {
private static Singleton instance;
private Singleton() {
}
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
4. 静态内部类: 在 Java 中,可以在类内部定义静态内部类,这些类可以直接访问外部类的静态成员,而无需创建外部类的实例。
public class OuterClass {
private static int outerStaticField = 10;
static class InnerClass {
public void accessOuterStaticField() {
System.out.println("Outer static field: " + outerStaticField);
}
}
}
(3) 关于Kotlin的静态方法
而Kotlin 中没有 static 关键字而是采用了类似于 C 语言的顶层函数和伴生对象(companion object )的方式来实现类似的功能。
1.Kotlin中的函数可以直接在类中定义。
class MyClass {
// 在类内定义的函数
fun classFunction() {
println("This is a member function of MyClass")
}
}
// 创建 MyClass 的实例
val obj = MyClass()
// 调用类内函数
obj.classFunction()
2.Kotlin 中的函数也可以在文件的顶层直接声明函数,称为顶层函数。
fun myFunction() {
println("This is a top-level function")
}
// 调用顶层函数
myFunction()
3.Kotlin 的伴生对象(Companion Object)。
在 Kotlin 类中,可以使用 companion object
关键字来定义一个伴生对象(可以有多个函数),其中的成员函数和属性可以在类的实例创建之前被调用,就像 Java 中的静态方法一样。
class MyClass {
companion object {
fun myFunction() {
println("This is a companion object function")
}
}
}
// 调用伴生对象的函数
MyClass.myFunction()
在 Kotlin 中,伴生对象(Companion Object)是一个在类内部声明的对象,它与该类的实例无关,但可以访问类的私有成员。
伴生对象的作用包括:
1. 模拟静态成员: 通过伴生对象,可以在 Kotlin 类中创建类级别的成员,这些成员在类的实例化过程中只会初始化一次,并且可以直接通过类名访问,类似于 Java 中的静态成员。
2. 访问类的私有成员: 伴生对象可以访问类的私有成员,这样就可以在伴生对象中定义一些与类紧密相关的辅助方法或属性,而不必暴露给类的外部。
3. 工厂方法: 伴生对象常用于实现工厂方法模式,它可以包含一个或多个用于创建对象实例的方法,这些方法可以直接通过伴生对象访问,并且可以根据需要返回不同类型的对象实例。
4. 接口实现: 在伴生对象中实现接口的方法可以使得这些方法与类关联在一起,同时不需要创建类的实例即可调用这些方法。
5. 命名空间组织: 当一个类需要包含一组相关的功能或工具方法时,可以使用伴生对象将这些功能组织在一起,提高代码的可读性和维护性。
(4)关于Kotlin与Java 互操作的补充
虽然 Kotlin 中没有直接对应于 Java 中的 static 关键字,但是 Kotlin 仍然支持与 Java 中的 static 相关的概念和用法,特别是在 与Java 互操作时。以下是一些在 Kotlin 中与 Java 中的 static 相关的用法:
1. 调用 Java 中的静态成员: 在 Kotlin 中,可以直接通过类名调用 Java 中的静态字段和方法,无需额外的修饰符。例如:
val result = MyClass.staticField // 访问 Java 类中的静态字段
MyClass.staticMethod() // 调用 Java 类中的静态方法
2. 定义伴生对象中的静态成员: 在 Kotlin 中,可以使用伴生对象来模拟 Java 中的静态成员。在伴生对象中定义的成员可以在类被加载时直接访问,无需类的实例。例如:
class MyClass {
companion object {
val staticField = 10 // 定义伴生对象中的静态字段
fun staticMethod() { // 定义伴生对象中的静态方法
println("This is a static method in companion object")
}
}
}
3. @JvmStatic 注解:在 Kotlin 中调用 Java 中的静态方法和字段时,也可以使用 @JvmStatic 注解: 这个注解可以使得 Kotlin 代码更接近 Java 中静态方法的调用方式。例如:
class MyClass {
companion object {
@JvmStatic
val staticField = 10
@JvmStatic
fun staticMethod() {
println("This is a static method in companion object")
}
}
}
四.类与对象
(1)类的继承
Java通常使用extends关键字来实现子类对父类的继承,类的继承是单一继承。
子类可以通过this关键字访问自己成员,通过super关键字访问父类成员。
当父类的常量、变量或方法需要修改,并且这种修改需要导致子类的大规模重构时,可以考虑以下解决方案:
1.使用接口: 将父类转换为接口,子类实现接口。这样,当父类的常量、变量或方法需要修改时,只需修改接口定义,而不会影响到子类。但这种方法可能需要更改大量的代码,因为接口不包含方法的实现。
2.使用抽象类: 如果父类是一个普通类而不是接口,并且需要修改它的属性或方法,可以将父类转换为抽象类。在抽象类中,你可以提供部分方法的默认实现,子类只需要实现其中的一部分方法。这样,当需要修改父类时,只需修改抽象类,而不需要修改所有的子类。
3.使用组合或委托: 将子类中对父类的依赖转换为组合或委托关系。这样,子类不再直接继承父类,而是通过组合或委托的方式使用父类的功能。当父类需要修改时,只需修改父类本身,而不需要修改子类。
4.使用设计模式: 例如,使用模板方法模式,将父类中的算法骨架定义为抽象方法,而将算法中的具体步骤延迟到子类中实现。这样,当需要修改父类时,只需修改模板方法,而不需要修改所有的子类。
(2)重载与重写
Java 的重载(Overloading)和重写(Overriding)是面向对象编程中常见的两个概念,它们有以下区别:
1.重载(Overloading):
重载指的是在同一个类中可以定义多个方法具有相同的名称,但参数列表不同的情况。
重载方法的特征是方法名称相同,但参数类型、参数个数或参数顺序不同。
重载方法可以有不同的返回类型。
编译器会根据调用时传递的参数类型和数量来选择调用哪个重载方法。
重载的使用场景:
当一个类需要提供多个功能相似但参数不同的方法时,可以使用重载。
当需要为同一个操作提供不同的参数组合时,可以使用重载。
例如,Java 中的构造函数就经常会进行重载,以便提供不同的初始化方式。
2.重写(Overriding):
重写指的是子类可以重新定义父类中已经定义的方法。
重写的方法名称、参数列表和返回类型必须与父类中被重写的方法相同。
重写可以改变方法的实现逻辑,但方法签名必须保持一致。
重写通常用于子类需要改变父类方法的行为或实现。
重写的使用场景:
当子类需要修改或补充父类的方法时,可以使用重写。
当子类需要提供一种不同于父类的实现逻辑时,可以使用重写。
重写常用于实现多态性,即通过父类引用指向子类对象时,调用的是子类重写的方法。
例如,当定义一个抽象类或接口时,需要子类来提供具体的实现时,就需要使用重写。
(3)Java中的抽象类
1.抽象类是一种类,它不能被实例化,只能被继承,只有其非抽象子类可以被实例化。
2.抽象类可以包含抽象方法(没有具体实现),也可以包含具体方法。有抽象方法的类一定是抽象类。
3.抽象类的构造方法和类方法(用static修饰的方法)不能声明为抽象方法
4.子类继承抽象类后,必须实现所有的抽象方法,否则子类也必须声明为抽象类。
5.抽象类的意义: 抽象类提供了一种模板或者基础类的概念,它定义了一些通用的行为和属性,但是并不提供具体的实现。抽象类可以作为其他类的基类,帮助实现代码重用和继承机制。
(4)Java中的接口
1. 接口是一种纯粹的抽象类,它只包含抽象方法和静态常量。
2.类可以实现一个或多个接口,实现接口的类必须提供接口中定义的所有方法的具体实现。
接口的意义: 接口定义了一种契约,规定了类应该具有的方法和常量,但是不涉及具体的实现细节。接口提供了一种多态性的实现方式,使得不同的类可以实现同一个接口,并且可以根据需要实现不同的功能。接口还促进了代码的模块化和解耦,使得系统更加灵活和易于扩展。