面向对象
基础语法
程序结构、打印语句、输入语句、数据类型与变量、运算符、条件判断语句、循环语句、数组。
publicclassHelloWorld{publicstaticvoidmain(String[]args){// 打印语句System.out.println("Hello, World!");// 输入语句Scannerscanner=newScanner(System.in);System.out.print("请输入姓名:");Stringname=scanner.nextLine();// 数据类型与变量intage=18;doublescore=95.5;booleanisPass=true;// 运算符intsum=age+2;booleanisAdult=age>=18;// 条件判断语句if(isAdult){System.out.println(name+" 已成年");}else{System.out.println(name+" 未成年");}// 循环语句for(inti=0;i<3;i++){System.out.println("第 "+(i+1)+" 次循环");}// 数组int[]scores={90,85,95};System.out.println("第一个成绩:"+scores[0]);}}类与对象
类与对象的概念
- 类的定义:使用
class关键字声明一个类,类是对象的模板,描述了对象共有的属性和行为 - 属性定义:在类中声明变量,用于描述对象的状态,例如学生的姓名、年龄等
- 方法定义:在类中声明方法,用于描述对象的行为,方法可以接收参数并返回结果,例如
public void study(String subject) - 类创建对象:通过
new 类名()的方式实例化对象,例如Student stu = new Student(); - 对象名调用对象的属性:通过
对象名.属性名访问对象的属性,例如stu.name - 对象名调用方法执行:通过
对象名.方法名()调用对象的方法,例如stu.study("Java")#### 封装
类的格式,系统中使用的类都是有封装的。
一个类包含哪些内容
面向对象的成员
- 属性:使用对象变量名调用
- 方法:使用对象变量名调用
构造方法
- 格式:没有返回值结构,且方法名与类名相同的方法,例如
public 类名(){} - 调用时机:在创建对象时自动调用,即执行
new 类名()时触发 - 作用:用于对象创建时的初始化,包括属性的初始化和方法的初始化调用
- 构造方法的重载:一个类中可以定义多个同名但参数列表不同的构造方法,以满足不同的创建需求
构造代码块
{}同样在对象创建时执行,可用于执行一些初始化操作。每当通过new创建一个对象时,构造代码块都会被调用一次。##### 静态资源
static关键字修饰的成员属于类本身,与具体的对象实例无关,因此可以直接通过类名调用,无需先创建对象。它的核心特性是唯一性:无论创建多少个对象,静态成员在内存中只有一份,被所有对象共享。
- 静态属性:在内存中只存在一份,所有对象共享同一份数据,通过类名直接调用,例如
类名.属性名 - 静态方法:通过类名直接调用,例如
类名.方法名();由于静态方法不依赖对象,因此不能直接使用本类中的实例属性或实例方法(即对象成员部分) - 静态代码块:在类被加载时执行,且只会执行唯一的一次,常用于完成一些全局性的初始化操作,例如加载配置文件、初始化数据库连接等
所谓实例,就是新对象,必须要用new的初始化一下
比如说:
publicclassDemo{// 静态变量:属于类,全局1份,所有对象共享staticintstaticNum=0;// 实例变量(没有static):属于每个对象,每个对象各自一份intinstanceNum=0;//静态代码块:类加载执行,只执行1次static{System.out.println("====静态代码块执行====");}//实例代码块,无static:每new对象就执行一次{System.out.println("====实例代码块执行====");}//静态方法publicstaticvoidstaticMethod(){System.out.println("这是static静态方法");// 可以访问静态变量System.out.println(staticNum);// 静态方法不能直接访问实例变量!编译报错// System.out.println(instanceNum);}//普通实例方法(无static)publicvoidinstanceMethod(){System.out.println("这是普通实例方法");// 普通方法,既可以访问静态,也可以访问实例变量System.out.println(staticNum);System.out.println(instanceNum);}publicstaticvoidmain(String[]args){//1.静态:直接用类名调用,不需要new对象Demo.staticMethod();Demo.staticNum=100;System.out.println("----------创建第一个对象----------");Demod1=newDemo();d1.instanceNum=10;staticNum++;//静态变量共享System.out.println("----------创建第二个对象----------");Demod2=newDemo();d2.instanceNum=20;staticNum++;//看结果System.out.println("d1实例变量:"+d1.instanceNum);//10,自己的System.out.println("d2实例变量:"+d2.instanceNum);//20,自己的System.out.println("静态staticNum:"+Demo.staticNum);//2,共享同一个!//普通方法,必须new对象才能调用d1.instanceMethod();}}逻辑是这样的:
当我们创建了一个新的对象(new),我们调用的静态变量自加一,而实例中的变量直接创建和赋值
运行结果如下:
====静态代码块执行====这是static静态方法100----------创建第一个对象----------====实例代码块执行====----------创建第二个对象----------====实例代码块执行====d1实例变量:10d2实例变量:20静态staticNum:102这是普通实例方法10210核心差异总结
- 静态static
• 属于类,类加载就产生,只一份
• 调用:类名.变量 / 类名.方法(),不用new对象
• 静态方法不能直接访问普通实例变量/方法
- 无static(实例)
• 属于对象,new创建对象之后才有,每个对象独立一份
• 调用:对象.变量 / 对象.方法(),必须new
• 普通实例方法,静态、实例的成员全都能访问
访问权限修饰符
public:修饰类、属性、方法,表示权限是公开的,在项目中都可以调用private:私有的,只能修饰类中的成员,权限是只能在本类中访问protected:只能在同一个包下和子类中访问- 缺省不写:类中缺省不写,同一个包下;接口中缺省不写,默认
public
继承与多态
继承的语法(extends)
继承是面向对象的重要特性,子类通过extends关键字继承父类的属性和方法,实现代码复用。
classAnimal{Stringname;publicvoideat(){System.out.println(name+" 正在吃东西");}}classDogextendsAnimal{publicvoidbark(){System.out.println(name+" 正在汪汪叫");}}方法重写(@Override)
子类可以重写父类的方法,使用@Override注解标记,表示该方法是对父类方法的重写。
classAnimal{publicvoidsound(){System.out.println("动物发出声音");}}classDogextendsAnimal{@Overridepublicvoidsound(){System.out.println("狗在汪汪叫");}}当然,我们也可以不写@Override注解,方法依然能够正常重写。不过这样做存在一些弊端:
- 缺少编译期检查:如果方法签名写错(例如参数类型、方法名拼写不一致),编译器不会报错,而是把它当作一个全新的方法,导致重写静默失败,运行时行为与预期不符。
- 可读性下降:阅读代码时,无法直观地看出该方法是对父类方法的重写,容易让其他开发者误以为这是一个新增方法,增加理解成本。
- 维护风险增加:当父类方法被修改或删除时,没有注解提示,子类中的方法可能悄然失去重写关系,留下难以排查的隐患。
因此,在重写父类方法时,建议始终加上@Override注解,让编译器帮我们校验重写是否正确,也让代码意图更加清晰。
多态的实现
多态是指同一个方法调用,在不同对象上表现出不同的行为。核心是父类引用指向子类对象。
Animalanimal=newDog();// 父类引用指向子类对象animal.sound();// 实际调用的是 Dog 类重写后的方法继承与多态实战示例
下面通过一个完整的 Java 示例,演示继承的语法、方法重写以及多态的实现。
// 父类:动物classAnimal{protectedStringname;publicAnimal(Stringname){this.name=name;}// 父类方法:发出声音publicvoidsound(){System.out.println(name+" 发出声音");}// 父类方法:吃东西publicvoideat(){System.out.println(name+" 正在吃东西");}}// 子类:狗,继承 AnimalclassDogextendsAnimal{publicDog(Stringname){super(name);}// 重写父类的 sound 方法@Overridepublicvoidsound(){System.out.println(name+" 汪汪叫");}// 子类特有方法publicvoidguard(){System.out.println(name+" 正在看家");}}// 子类:猫,继承 AnimalclassCatextendsAnimal{publicCat(Stringname){super(name);}// 重写父类的 sound 方法@Overridepublicvoidsound(){System.out.println(name+" 喵喵叫");}}publicclassTestPolymorphism{publicstaticvoidmain(String[]args){// 父类引用指向子类对象(多态)Animaldog=newDog("旺财");Animalcat=newCat("咪咪");// 调用重写后的方法dog.sound();cat.sound();// 调用父类中未重写的方法dog.eat();cat.eat();// 子类特有方法需要通过子类类型调用DogrealDog=newDog("大黄");realDog.guard();}}运行结果:
旺财 汪汪叫 咪咪 喵喵叫 旺财 正在吃东西 咪咪 正在吃东西 大黄 正在看家通过这个示例可以看到:子类通过extends继承父类的属性和方法,实现代码复用;通过@Override重写父类方法,让不同子类表现出不同的行为;多态让父类引用可以指向任意子类对象,使代码更加灵活和可扩展。
封装
- 封:使用受限制的权限修饰符修饰属性或者方法,使得这个类的对象不能直接调用这个属性赋值,不能直接调用方法执行。比如使用
private - 装:提供一套公开的访问方式
- 给属性赋值:setter 方法
publicvoidset属性名(参数){this.属性名=参数;} - 获取属性的值:getter 方法
public数据类型 get属性名(){return属性;}
- 给属性赋值:setter 方法
封装实战示例
下面通过一个完整的 Java 示例,演示private属性、setter/getter 方法、构造方法重载以及静态方法调用的实际使用场景。
publicclassStudent{// private 属性:外部不能直接访问privateStringname;privateintage;// 构造方法重载一:无参构造publicStudent(){System.out.println("调用无参构造方法");}// 构造方法重载二:带两个参数publicStudent(Stringname,intage){this.name=name;this.age=age;System.out.println("调用带参构造方法");}// setter 方法:给属性赋值publicvoidsetName(Stringname){this.name=name;}publicvoidsetAge(intage){if(age<0||age>150){System.out.println("年龄不合法,拒绝赋值");return;}this.age=age;}// getter 方法:获取属性的值publicStringgetName(){returnname;}publicintgetAge(){returnage;}// 静态方法:类名直接调用publicstaticvoidshowSchool(){System.out.println("学校:某某大学");}// 普通方法:展示学生信息publicvoidshowInfo(){System.out.println("姓名:"+name+",年龄:"+age);}publicstaticvoidmain(String[]args){// 通过无参构造创建对象,再使用 setter 赋值Students1=newStudent();s1.setName("张三");s1.setAge(20);s1.showInfo();// 通过带参构造创建对象,直接初始化属性Students2=newStudent("李四",22);s2.showInfo();// 非法年龄赋值会被拦截s2.setAge(200);// 静态方法通过类名直接调用Student.showSchool();}}运行结果:
调用无参构造方法 姓名:张三,年龄:20 调用带参构造方法 姓名:李四,年龄:22 年龄不合法,拒绝赋值 学校:某某大学通过这个示例可以看到:外部无法直接访问private属性,只能通过 setter/getter 方法读写,从而在赋值时加入校验逻辑,保证数据安全;构造方法重载让对象创建更灵活;静态方法则无需创建对象即可通过类名调用。
总结
- 代码格式更加规范,可读性更好
- 数据的安全性更好
- 读写分离