Java学习笔记之面向对象
面向对象编程
1 类的调用
- 静态方式
//Student.java
public class Student {
public static void sayHi(){
System.out.println("Hello World!");
}
}
//main.java
public class main {
public static void main(String[] args) {
Student.sayHi();
}
}
- 非静态方式
//Student.java
public class Student {
public void sayHi(){
System.out.println("Hello World!");
}
}
//main.java
public class main {
public static void main(String[] args) {
Student student = new Student();
student.sayHi();
}
}
- 静态方法和非静态方法
//可以直接调用
public static void a(){
b();
}
public static void b(){}
//可以直接调用
public void a(){
b();
}
public void b(){}
//不可以调用
//方法 a 由 static 修饰,与类一起加载
//方法 b 无 static 修饰符,只有实例化之后才会在内存中加载,因此此种调用方式错误
public static void a(){
b();
}
public void b(){}
2 值传递和引用传递
- 值传递
public class main {
public static void main(String[] args) {
int num = 5;
System.out.println(num); //num = 5
change(num);
System.out.println(num); //num = 5
}
public static void change(int num){
num = 100;
}
}
- 引用传递
public class main {
public static void main(String[] args) {
Person person = new Person();
System.out.println(person.name); //null
main.change(person);
System.out.println(person.name); //Bob
}
public static void change(Person person){
person.name = "Bob";
}
}
class Person {
String name;
}
3 类的实例化
- 构造函数
// new 的本质,就是在调用构造器
public class Person {
String name;
//无参构造
public Person(){
this.name = "Bob";
}
//有参构造
public Person(String name){
this.name = name;
}
}
- 内存分析
public class main {
public static void main(String[] args) {
Pet dog = new Pet();
dog.name = "旺财";
dog.age = 3;
dog.shout();
Pet cat = new Pet();
}
}
public class Pet {
public String name;
public int age;
public void shout(){
System.out.println("Shout!");
}
}
4 三大特性
封装
public class Pet {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
if (age < -1 || age > 120){
this.age = 3;
}else{
this.age = age;
}
}
}
public class main {
public static void main(String[] args) {
Pet dog = new Pet();
dog.setAge(500);
System.out.println("age = " + dog.getAge()); //age = 3
}
}
- 封装的作用:
- 提高程序安全性,保护数据
- 隐藏代码实现细节
- 统一接口
get / set
- 系统可维护性增加
继承:本质是对一批类的抽象,使用关键字 extends
public class Pet {
private String name = "Bob";
protected int age = 5;
int money = 100;
public void shout(){
System.out.println("Hi");
}
}
public class Cat extends Pet {}
public class main {
public static void main(String[] args) {
Cat cat = new Cat();
cat.shout(); //Hi
System.out.println(cat.name); //Error
System.out.println(cat.age); //5
System.out.println(cat.money); //100
}
}
- 子类会继承父类中
public、protected、default
修饰的所有属性和方法,private
修饰的则不会被继承 Java
中所有的类,都默认继承Object
类Java
中的类都是单继承,没有多继承- 私有属性和方法均无法被继承
public class Pet {
public String name = "Pet";
public void shout(){
System.out.println("Father");
}
}
public class Cat extends Pet {
public String name = "Cat";
public void print(){
System.out.println("Son");
System.out.println(super.name);
super.shout();
}
}
public class main {
public static void main(String[] args) {
Cat cat = new Cat();
cat.print();
// Son Pet Father
}
}
-
super
注意点super
调用父类的构造方法时,必须出现在子类构造方法的第一行super
必须只能出现在子类的方法或者构造方法中super
和this
不能同时调用构造方法
-
super VS this
- 代表的对象不同
this
:本身调用者这个对象super
:代表父类的引用
- 适用前提不同
this
:有无继承均可使用super
:只能在继承的条件下使用
- 构造方法
this
:本类的构造方法super
:父类的构造方法
- 代表的对象不同
-
方法重写
- 方法名与参数列表必须一致
- 修饰符的范围可以扩大,但不能缩小
public > protected > default > private
- 抛出的异常,范围可以扩大不能缩小
- 子类重写父类方法,只是方法体不同
//使用 static 关键字:方法的调用只和左边的类型有关
public class B {
public static void test(){
System.out.println("B ==> test()");
}
}
public class A extends B{
public static void test(){
System.out.println("A ==> test()");
}
}
public class main {
public static void main(String[] args) {
A a = new A();
a.test(); //A ==> test()
B b = new A();
b.test(); //B ==> test()
}
}
//方法重写:重写的定义只针对无 static 修饰的方法
public class B {
public static void test(){
System.out.println("B ==> test()");
}
}
public class A extends B{
//对父类的 test() 方法进行了重写
@Override
public static void test(){
System.out.println("A ==> test()");
}
}
public class main {
public static void main(String[] args) {
A a = new A();
a.test(); //A ==> test()
B b = new A();
b.test(); //A ==> test()
}
}
多态
public class Person {
public void run(){
System.out.println("Person ==> run()");
}
}
public class Student extends Person{
@Override
public void run() {
System.out.println("Student ==> run()");
}
public void eat(){
System.out.println("Student ==> eat()");
}
}
public class main {
public static void main(String[] args) {
Student s1 = new Student();
Person s2 = new Student();
Object s3 = new Student();
s1.run(); //Student ==> run()
s1.eat(); //Student ==> eat()
((Student) s2).eat(); //Student ==> eat()
}
}
- 多态注意事项
- 多态是方法的多态,属性没有多态
- 父类与子类必须有联系,否则就会转换异常
ClassCastException
- 子类需要对父类方法进行重写,父类的引用对象指向子类
- 类的类型转化
- 父类的引用指向子类的对象
- 子类转为父类,是低转高,向上转型,直接转换
- 父类转为子类,是高转低,向下转型,要强制转换,父类可能会丢失一些原有的方法
5 static 关键字
public class Person {
{
System.out.println("匿名代码块");
}
static {
System.out.println("静态代码块");
}
Person(){
System.out.println("构造方法");
}
public static void main(String[] args) {
Person person1 = new Person();
System.out.println("-----------");
Person person2 = new Person();
}
}
/*
静态代码块
匿名代码块
构造方法
---------
匿名代码块
构造方法
*/
- 静态代码块和类一起加载,且只加载一次
- 匿名代码块在构造方法之前加载
6 抽象类
- 使用关键字
abstract
修饰 - 抽象类与抽象方法的作用是实现约束
- 子类如果继承了抽象类,那么就必须实现父类的抽象方法,除非子类也是抽象类
- 不能
new
抽象类,只能靠子类去实现 - 抽象类里可以写普通方法,但是普通类里不能写抽象方法,抽象方法只能在抽象方法中
public abstract class Person {
public abstract void doSomething();
}
public class Student extends Person{
@Override
public void doSomething() {
}
}
- 抽象类也有构造方法
public abstract class Person {
public abstract void doSomething();
Person(){
System.out.println("构造方法");
}
}
public class Student extends Person{
@Override
public void doSomething() {
System.out.println("doSomeThing()");
}
}
public class main {
public static void main(String[] args) {
Student student = new Student();
}
}
//构造方法
7 接口
- 类、抽象类、接口
- 类:只有具体实现
- 抽象类:具体实现的规范(抽象方法)都具有
- 接口:使用关键字
interface
,只有规范,自己无法写方法,实现约束和具体步骤的分离,更加规范
- 接口中所有的方法,其实都是抽象的,默认使用
public abstract
修饰
public interface UserAction {
void run();
}
- 类实现接口使用关键字
implements
- 实现了接口的类,就必须重写接口中的所有方法,接口可以“多继承”
public interface UserAction {
void add(String name);
void delete(String name);
void update(String name);
void query(String name);
}
public interface UserTime {
void timer(String name, int age);
}
public class UserActionImpl implements UserAction, UserTime{
@Override
public void add(String name) {
}
@Override
public void delete(String name) {
}
@Override
public void update(String name) {
}
@Override
public void query(String name) {
}
@Override
public void timer(String name, int age) {
}
}
8 内部类
- 一般内部类(可以访问外部类的私有属性)
public class Outer {
private final int id = 10;
public void printOut(){
System.out.println("外部类的方法");
}
class Inter {
public void printIn(){
System.out.println("内部类方法");
}
public void getOutId(){
System.out.println(id);
}
}
}
public class main {
public static void main(String[] args) {
Outer outer = new Outer();
Outer.Inter inter = outer.new Inter();
inter.getOutId(); //10
}
}
- 局部内部类
public class Outer {
public void method(){
class test{
}
}
}
- 匿名内部类
public class main {
public static void main(String[] args) {
new Apple().eat();
}
}
class Apple{
public void eat(){
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!