2.3 java程序基础
2.3.2 变量和数据类型
var关键字:
作用:省略变量类型
StringBuilder sb = new StringBuilder()//因为类型名过长,所以可以使用关键字来省略变量类型
var sb = new StringBuilder()//因为编译器会自动推断出sb的变量类型
字符串:
转义字符:
误区:字符串的不可变性
原来以为是s的值被覆盖了,其实是指针指向变了。
这里要和变量的赋值区分。
关键点:变量赋新值,覆盖;给新的变量赋值,就是转义指针指向的存储单元
对于变量:
这里再次打印n的值,答案是200
对于字符串:
字符串不可变
public class Main {
public static void main(String[] args) {
String s = "hello";
String t = s;
s = "world";
System.out.println(t); // t是"hello"还是"world"?
}
}
这里打印的t还是hello,因为这里的不是赋值操作
2.4 流程控制
以下是这些占位符对应的英文解释:
- `%d`:Decimal(十进制整数)
- `%x`:Hexadecimal(十六进制)
- `%f`:Floating-point number(浮点数)
- `%e`:Scientific notation for floating-point number(科学计数法表示的浮点数)
- `%s`:String(字符串)
3 面向对象编程
3.1.1 方法
这里因为两个作用域都是private,没有交集。所以类的属性不能传递
// private field
public class Main {
public static void main(String[] args) {
Person ming = new Person();
ming.setName("Xiao Ming"); // 设置name
ming.setAge(12); // 设置age
System.out.println(ming.getName() + ", " + ming.getAge());
}
}
class Person {
private String name;
private int age;
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return this.age;
}
public void setAge(int age) {
if (age < 0 || age > 100) {
throw new IllegalArgumentException("invalid age value");
}
this.age = age;
}
}
总结:
this变量用法
用于访问当前实例
当局部变量和参数字段重合时,局部变量优先级高此时必须使用this
方法参数:灵活调用
这里使用public方法,间接修改了private字段
public static void main
private static final
public static final
public static final int
public static final String
上述五种,实际的应用场景是什么?请给出代码和解释
以下是对这五种情况的应用场景解释,并附带了简单的代码示例:
public static void main
:这是 Java 程序的入口点。当运行 Java 程序时,会从这个方法开始执行。
public class MainClass {
public static void main(String[] args) {
// 这里编写程序的主要逻辑
System.out.println("Hello, World!");
}
}
private static final
:private
表示该成员只能在当前类中访问,static
表示该成员属于类而不是类的实例,final
表示该成员的值一旦被初始化就不能再被修改。
public class MyClass {
private static final int CONSTANT_NUMBER = 10;
public static void main(String[] args) {
// 无法修改 CONSTANT_NUMBER 的值
// CONSTANT_NUMBER = 20; // 错误,无法重新赋值
System.out.println(CONSTANT_NUMBER);
}
}
public static final
:public
表示该成员可以在任何地方访问,static
表示该成员属于类而不是类的实例,final
表示该成员的值一旦被初始化就不能再被修改。
public class GlobalConstants {
public static final String APP_NAME = "MyApp";
public static void main(String[] args) {
System.out.println(APP_NAME);
}
}
public static final int
:与上述类似,明确指定了类型为整数。
public class IntConstants {
public static final int MAX_VALUE = 100;
public static void main(String[] args) {
if (50 < MAX_VALUE) {
System.out.println("50 is less than MAX_VALUE");
}
}
}
public static final String
:明确指定了类型为字符串。
public class StringConstants {
public static final String GREETING = "Hello";
public static void main(String[] args) {
System.out.println(GREETING + ", World!");
}
}
这些关键字的组合使用可以根据具体的编程需求来控制成员的访问权限、存储方式和可修改性,以提高代码的安全性、可读性和可维护性。
3.1.2 构造方法
无参数构造方法是默认的构造方法;
有参数构造方法是自定义的构造方法;
如何在调用时,同时使用两者呢?
问题
:
既对字段进行初始化,又对字段进行初始化。
答:
class Person{
public Person(){
}
public Person(String name,int age){
this.name = name;
this.age = age;
}
public String getName() {
return this.name;
}
public int getAge() {
return this.age;
}
private String name = "Unamed";
private int age = 10;
}
public class Main {
public static void main(String[] args) {
Person ming = new Person("arii", 22);
Person arii = new Person();
System.out.println(ming.getName() + ","+ming.getAge());
System.out.println(arii);
}
}
对象最终由构造方法所确定(即使是初始化了字段,但是构造方法在类中后执行,所以最终输出又构造方法决定)。
3.1.3 重载方法
在一个类中,只有参数不同,功能类似且同名的方法叫重载方法
3.1.4 继承
现在要通过继承的方式实现复用代码
class Person{
private String name;
private int age;
public String getName() {
return this.name;
}
public int getAge() {
return this.age;
}
public void setName(String name) {
this.name = name;//这个实例中的name
}
public void setAge(int age) {
if (age < 0 || age >100){
throw new IllegalArgumentException("invalid age value");
}
this.age = age;
}
}
class Student extends Person{
private int score;
public int getScore(){
return score;
}
public void setScore(int score){
this.score = score;
}
}
public class Main {
public static void main(String[] args) {
Person arii = new Person();
arii.setAge(12);
arii.setName("arii");
System.out.println(arii.getName()+arii.getAge());
Student xiaolv = new Student();
xiaolv.setScore(400);
System.out.println(xiaolv.getName()+xiaolv.getScore());
}
}
3.1.4.1 继承特性的特点:
- 一个类只有一个父类,object除外
- 一个类可以有多个子类
- 子类无法访问父类的private字段或者private方法,当子类需要访问父类的private字段或方法时,将private改为protected
特殊情况: super.name()
在Student
的构造方法中,无法调Person
的构造方法。
class Person{
protected String name;
protected int age;
public Person(String name, int age){
this.name = name;
this.age = age;
}
}
class Student extends Person{
protected int score;
public Student(String name,int age, int score){
this.score = score;
}
}
public class Main {
public static void main(String[] args) {
Student s = new Student("arii",12,99);
}
}
3.1.4.2 阻止继承
用于一些框架中,防止继承被滥用。
public final class。
final修饰符定义类,如果类被初始化,则不能被修改。即不能被继承
3.1.4.3 向上转型
理解:
使用向上转型的本质即使把子类变成父类了,之前做项目的了解是,当子类有处理不了的参数时,会统一回传给父类,直到父类也处理不了,再统一抛出异常?
GPT纠错
:
向上转型的本质不是把子类“变成”父类,而是将子类对象视为父类对象来处理。
在向上转型中,子类对象可以被当作父类对象使用。但需要注意的是,通过父类引用访问对象时,只能访问父类中定义的成员(包括属性和方法),而不能直接访问子类特有的成员。
关于处理参数和异常的情况,通常不是将处理不了的参数统一回传给父类。而是在子类重写父类的方法时,如果子类的方法处理逻辑无法处理某些情况,并且子类没有提供特定的处理方式,那么会按照父类中该方法的定义来执行。
如果父类方法中也没有处理异常的逻辑,并且异常未被捕获,那么会向上传播,直到被捕获或者导致程序终止。
总之,向上转型主要是为了实现多态和代码的灵活性,而不是简单地将处理不了的任务回传给父类。
3.1.4.4 向下转型
使用instance of
来判断示例的类型,但是无法区分具体是父类还是子类
3.1.4.5 组合、继承
class Person{
protected String name;
protected int age;
public Person(String name, int age){
this.name = name;
this.age = age;
}
public String toUpperCase(){
return this.name.toUpperCase();
}
}
class Book{
protected String name;
public String getName(){
return name;
}
public void setName(String name) {
this.name = name;
}
}
class Student extends Person{
protected Book book;
protected int score;
public Student(String name,int age, int score){
super(name,age);//只对name和age取父类,因为score来源于子类
this.score = score;
}
}
public class Main {
public static void main(String[] args) {
//向上转型
Person s = new Student("arii",12,99);
System.out.println(s.name+""+s.age+"");
System.out.println(s instanceof Student);
//向下转型
Person p = new Student("xiaolv",22,100);
if (p instanceof Student){
Student t = (Student) p;//向下强制转型
System.out.println(p.toUpperCase());//这是大写操作
System.out.println(t.name+""+t.age+""+t.score);//这是Person类型,就转换成了Student类型
}
// if (p instanceof Student t){
Student t = (Student) p;//向下强制转型
// System.out.println(t.name+""+t.age+""+t.score);//这是Person类型,就转换成了Student类型
// }
//组合
Person l = new Student("arii",22,99);
System.out.println(l.name+""+l.age+""+l.book);
System.out.println(l instanceof Student);
}
}
在这里book变量属于student成员,所以找不到book变量
3.1.5 覆写——多态
覆写和重载的区别:
当方法签名相同,返回值(参数类型和名称要相同)也相同时,是Override
.子类对父类
当方法签名不同,就是overload。子类对父类
class Person{
public void run(){
System.out.println("Person run");
}
}
class Student extends Person{
@Override
public void run() {
System.out.println("Student run");
}
}
public class Main {
public static void main(String[] args) {
Person p = new Student();
p.run();
}
}
子类覆写了父类的方法,所以运行的就是子类
3.1.6 抽象类和接口
在上述代码运行后,我们可以发现父类实际上没有实际意义。但是因为多态的特性,我们又不能去掉Person类的run方法。
所以要使用抽象方法
,而抽象方法所在的类即为抽象类
。
抽象类只能被继承,而抽象方法必须被覆写(重写),被称为规范
。
面向抽象编程
尽量引用高层类型,避免引用实际子类型,称做"面向抽象编程"(OOP)。
接口:
public class Main {
public static void main(String[] args) {
Person s = new Student("arii");//这里卡住了,别忘了创建实例
s.run();
s.getName();
}
}
interface Person{
void run();
String getName();
}
class Student implements Person{
private String name;
public Student(String name){
this.name = name;
}
@Override
public void run() {
System.out.println("Student is running");
}
@Override
public String getName() {
System.out.println(name);
return name;
}
}
编写代码时,注意两个报错。报错1是创建Student 接收对象。报错2是要注意所有子类在覆写父类接口时,要重写全部方法。除非父类的方法是default方法
继承关系
=
了,别忘了创建实例
s.run();
s.getName();
}
}
interface Person{
void run();
String getName();
}
class Student implements Person{
private String name;
public Student(String name){
this.name = name;
}
@Override
public void run() {
System.out.println("Student is running");
}
@Override
public String getName() {
System.out.println(name);
return name;
}
}
编写代码时,注意两个报错。报错1是创建Student 接收对象。报错2是要注意所有子类在覆写父类接口时,要重写全部方法。除非父类的方法是`default方法`
###### 继承关系
![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/8ae6523f583b4128ada31043bfac6ac9.png#pic_center)
公共逻辑放在`abstract class`中,具体逻辑放在子类中