面向对象
重点: 构造器/构造方法
引入
我们来看一个需求: 前面我们在创建人类的对象时, 是先把一个对象创建好后, 再给他的年龄和姓名属性赋值, 如果现在我要求, 在创建人类的对象时, 就直接指定这个对象的年龄和姓名, 该怎么做? 这时就可以使用构造器.
语法
public class Study
{
public static void main(String args[])
{
Person p = new Person(70,"杜舆江");
//在创建p对象时直接为其属性赋值
}
}
class Person
{
int age;
String name;
//构造器语法
//1.构造器名应与类名一致: Person.
//2.没有返回值: 不可以写void int等, 也不可以在代码块的最后加入return.
//3.在创建对象时, 系统会自动地调用该类的构造器完成对象的初始化.
//4.形参列表与定义方法时的规则一致.
//5.构造器前也有访问修饰符.
public Person(int pAge,Sting pName)
{
age = pAge;
name = pName;
}
}
要点
一个类可以定义多个不同的构造器, 即构造器重载
public class Study
{
public static void main(String[] args)
{
//构造器重载, 我的实参既可以是数字, 也可以是数字和字符串
Person p1 = new Person(20);
Person p2 = new Person(19,"小杜");
cout
}
}
class Person
{
int age = 18;
String name;
public Person(String pName);
{
age = pName;
}
public Person(int pAge,String pName)
{
age = pAge;
name = pName;
}
}
2.如果程序员没有定义构造器, 系统会自动给类生成一个默认无参构造器(也叫默认构造器), 可以用反编译去看.
3.一旦自己定义了自己的构造器, 默认的构造器就被覆盖了, 就不能再使用默认的无参构造器, 如果想使用, 必须显式定义一下.
public class Exercise {
public static void main(String[] args) {
Person person = new Person(18,"Jack");
Person person1 = new Person();
//如果没有显式定义, 无法运行, 会报错
System.out.println("运行成功");
}
}
class Person {
int age;
String name;
public Person(int age, String name) {
this.age = age;
this.name = name;
}
//显示定义
public Person() {
}
}
对象创建流程
public class Exercise {
public static void main(String[] args) {
Person jack = new Person(18, "Jack");
}
}
class Person {
int age = 10;
String name;
public Person(int age, String name) {
this.age = age;
this.name = name;
}
}
1.加载Person类信息(Person.class),只会加载一次
2.在堆中分配空间(地址)
3.完成对象初始化[3.1默认初始化 age = 0 name = null(都为默认值) 3.2显式初始化, age = 18 name = null 3.3 构造器初始化 age = 18 name = Jack]
4.把对象在堆中地址, 返回给p(对象名)
this关键字
理解
this 可以理解为替换对象 ,此时涉及的是哪个对象, 那么 this 就是它
语法
public class Exercise {
public static void main(String[] args) {
Person jack = new Person(18, "Jack");
//在这里
//this.age 和 Jack.age相同
//this.name 和 Jack.name相同
}
}
class Person {
int age = 10;
String name;
public Person(int age, String name) {
this.age = age;
this.name = name;
}
}
要点
1.this 关键字可以用来访问本类的属性, 方法, 构造器
2.访问成员方法的语法: this.方法名(参数列表)
3.访问构造器语法:this(参数列表); 注意只能在构造器中使用(即只能在构造器中访问另外一个构造器, 必须放在第一 条语句)
4.this.方法调用 与 方法调用不同(区别在继承讲)
public class Exercise {
public static void main(String[] args) {
Person person = new Person();
System.out.println(person.age + "\t" + person.name);
person.sayHello();
person.Marry();
}
}
class Person {
int age;
String name;
public void sayHello() {
System.out.println("Hello!");
}
//this 在方法中的使用
public void Marry() {
this.sayHello();
System.out.println("Let's marry!");
}
public Person(int age, String name) {
this.age = age;
this.name = name;
}
//this 在构造器中的使用
public Person() {
this(18, "Jack");//必须在该构造器的第一行
System.out.println("成功!");
}
}
4.this 不能在类定义的外部使用,只能在类定义的方法中使用。
包
引入
现在有两个程序员共同开发一个Java项目, 程序员小明希望定义一个类取名 dog, 程序员小强也想定义一个类也取名dog. 如何解决?
本质
创建文件夹来存储类, 不同文件夹中可以有同名类
打包语法
该语句必须写在文件的开头, 且只能写一个
package com.hspedu;//com.hspedu是包名
包的调用语法
import java.util.Scanner;
//调用 util 包的 Scanner 类
命名
一般是小写字母 + 小圆点
一般是com.公司名.项目名.业务模块名
com.sina.crm.user//用户模块
常用的包
java.lang.* //lang 包 是基本包, 默认引入, 不需要再引入
java.util.* //util 包, 系统提供的工具包, 工具类, 使用Scanner
java.net.* //网络包, 网络开发
java.awt.* //是做 Java 的界面开发, GUI
访问修饰符
定义
访问修饰符可以用来修饰类中的属性, 方法以及类本身.
4种访问修饰符
1 | 访问级别 | 访问控制修饰符 | 同类 | 同包 | 子类 | 不同包 |
2 | 公开 | public | √ | √ | √ | √ |
3 | 受保护 | protected | √ | √ | √ | × |
4 | 默认 | 没有修饰符 | √ | √ | × | × |
5 | 私有 | private | √ | × | × | × |
细节
只有默认和 public 可以修饰类.
重点: 封装
介绍
封装就是把抽象出的数据[属性]和对数据的操作[方法]封装在一起, 数据被保护在内部, 程序的其他部分只有通过被授权的操作[方法], 才能 对数据进行操作
优势
隐藏实现细节
可以对数据进行验证, 保证安全合理
封装三步
将属性进行私有化 -> 在类的外部不能随意修改属性
提供 public 的 set 方法, 用于对属性判断并进行赋值
public void setXxx(类型 参数名){
属性 = 参数名;
}
提供 public 的 get 方法, 用于获取属性信息
public 数据类型 getXxx(){
return xx;
}
封装与构造器的结合
引入
我们使用封装, 可以是数据受到保护, 不能随意改变, 且有一定要求, 但我们用构造器创建对象, 这里的数据并没有受到限制, 如何解决?
解决方法
public Person(String name, int age, double salary){
//构造器
//this.name = name;
//this.age = age;
//this.salary = salary;
//封装与构造器的结合
setName(name);
setAge(age);
setSalary(salary);
}
重点: 继承
引入
编写两个类, 这两个类有大量重复的属性, 方法, 如何减少重复 -> 继承
继承的本质
获取父类的属性, 方法
加载属性, 方法信息(顺序是: 从 object 向下)
调用时, 逐级上推, C中未找到的属性到 B 中找, 直到object
test
package com.Study.inherit;
public class test {
public static void main(String[] args) {
C c = new C();
System.out.println(c.name);
}
}
A
package com.Study.inherit;
public class A {
int age = 18;
String name = "杜舆江";
}
B
package com.Study.inherit;
public class B extends A{
int age = 20;
}
C
package com.Study.inherit;
public class C extends B{
int sal = 2000;
}
JVM 演示
![](https://i-blog.csdnimg.cn/blog_migrate/94d7375d973ba6f791557c8d39ae6c5f.png)
语法
测试类
package com.Study.inherit;
public class test {
public static void main(String[] args) {
B b = new B();
System.out.println(b.age);
}
}
A类
package com.Study.inherit;
public class A {
public int age;
public String name;
public A() {
}
public A(int age, String name) {
this.age = age;
this.name = name;
}
}
B类
package com.Study.inherit;
public class B extends A{//B继承了A
}
要点
子类继承了所有的属性和方法,非私有的属性和方法可以在子类直接访问, 但是私有属性和方法不能在子类直接访 问,要通过父类提供公共的方法去访问.
package com.Study.inherit;
public class B extends A{
int age = 20;
private int num = 100000;
//在子类中无法获取 num 的数值
//用如下方法, 构造一个get函数
public int getNum() {
return num;
}
}
子类必须调用父类的构造器,完成父类的初始化.
每个类都有默认的构造器, 构造器内默认有super();去完成父类的初始化.但是如果, 父类没有无参构造器, 我们需要写出super(对应的形参列表);来完成父类的初始化
B
package com.Study.inherit;
public class B extends A{
int age = 20;
private int num = 100000;
public int getNum() {
return num;
}
public B(int age, int num) {
this.age = age;
this.num = num;
System.out.println("B类(int age, int num)构造器被调用");
}
public B() {
System.out.println("B类无参构造器被调用");
}
}
C
package com.Study.inherit;
public class C extends B{
public C() {
super(20,40);
}
int sal = 2000;
}
test
package com.Study.inherit;
public class test {
public static void main(String[] args) {
C c = new C();
System.out.println(c.name);
}
}
输出
B类(int age, int num)构造器被调用
杜舆江
super 在使用时,必须放在构造器第一行(super 只能在构造器中使用)
java 所有类都是 Object 类的子类, Object 是所有类的基类.
子类最多只能继承一个父类(指直接继承),即 java 中是单继承机制
继承后的调用本质是逐级向上查找, 若查找到的方法, 属性等是私有的或未查找到会报错.
super
作用
super 代表父类的引用,用于访问父类的属性、方法、构造器.(不限于直接父类)
语法
调用父类构造器
super(形参列表);
调用父类方法
super.方法(形参列表);
调用父类属性
super.属性;
重点:多态
IDEA
快捷键
可在 Settings-Keymap 中配置
删除当前行: ctrl + y
复制当前行并粘贴至下一行: ctrl + d
补全代码: alt + /
增加/取消注释: ctrl + /
导入该行需要的类: 选中,alt + enter
快速格式化代码: ctrl + alt + L
运行程序: shift + f10
生成构造器、继承: alt + insert(insert 使用需要配合 fn)
查看一个类的层级关系: ctrl + H
将光标放在一个方法上, 输入ctrl + B, 可以选择定位到方法
自动地分配变量名, 通过在后面.var
查看子、父类关系: ctrl + H
模板
file-settings-editor-Live templates 可以查看有哪些模板, 也可以自定义添加修改
main
sout
fori
setXxx -> 生成属性 xxx 的 set 方法