Java
day7——2023.8.11
this关键字
this关键字,表示的是当前对象的意思
this可以用来调用属性、调用方法、调用构造方法
this调用属性
this调用属性的时候,指向的是当前对象
public class Person {
String name;
//和谁聊天的方法
//this表示当前对象的意思,指向方法的当前调用对象
//谁调用,就指向谁
//this在方法中使用的时候,如果方法中存在和属性同名的局部变量
//加上this可以表示指向对象的属性
public void say(String name){
System.out.println(this.name + "和" + name +"正在聊天!");
}
public Person() {
}
//构造方法中的this,在调用属性的时候
//表示,将来通过这个构造方法创建的对象的属性的值就是传入的值
//this就是指向创建的对象
public Person(String name) {
this.name = name;
}
public static void main(String[] args) {
Person p1 = new Person();
p1.name = "张三";
p1.say("王五"); //张三和王五在聊天
Person p2 = new Person();
p2.name = "李四";
p2.say("王五"); //李四和王五在聊天
Person p3 = new Person("张无忌");
Person p4 = new Person("赵敏");
}
}
this调用成员方法
public class Student {
public void say(){
System.out.println("学生在说话!");
}
public void say(String name){
System.out.println("学生在和" + name + "说话");
}
public void sleep(){
say();
//this调用当前类的成员方法的时候,可以省略不写
// this.say();
this.say("张三");
// System.out.println("学生在说话!");
System.out.println("学生在睡觉!");
}
public static void main(String[] args) {
Student s = new Student();
s.sleep();
}
}
this调用构造方法
this调用构造方法的时候,只能在构造方法中的第一行调用
public class Demo01 {
String name;
int age;
public Demo01(){
this("jack"); //调用的是name参数的构造方法
System.out.println("这是无参构造!1");
}
public Demo01(String name) {
this(20); //这个调用的是age参数的构造
System.out.println("这是参数为name的构造方法!2");
}
public Demo01(int age) {
this.show();//调用的 普通方法show
System.out.println("这是参数为age的构造方法!3");
}
public void show(){
//普通方法中,不能通过this调用构造方法
//this("jack");
System.out.println("这是普通方法!4");
}
public static void main(String[] args) {
new Demo01(); //
}
}
封装的定义、封装的使用、封装目的
定义: 封装其实是对象的一种隐藏技术,目的是将对象中的属性和方法组织起来,同时隐藏不想暴露的属性和方法的实现细节
用户或者其他对象就不能看到,也不能修改这些被隐藏的实现
将来只能通过指定的接口去调用对象的方法,从而达到通信的目的。
使用: 封装通过private关键字来使用,将这个关键字写在需要封装的属性或者方法之前即可
目的: 为了将设计者和使用者分开,使用者不需要知道实现的细节,只需要设计者提供的方法来访问对象就可以了
问题: 私有化之后的属性,无法被对象直接调用,怎么完成赋值和 值的获取?
对象属性的赋值 :
1,通过 全参的构造方法 赋值
2,通过在类中设定 set方法,对象调用set方法,来完成对象的赋值
获取对象的属性值:
在别的类中,想要获取属性的值,只能通过get方法来获取
总结 :
属性在私有化之后,一般需要给属性指定getter/setter方法
如果类和类之间需要产生属性的数据交互,那么就可以通过 getter/setter方法
package com.iweb.airui369.day06;
public class School {
//属性
private String schoolName;
private int studentNumber;
private int teacherNumber;
private int classNumber;
//set方法,就是普通方法,返回值为空,需要传入参数用来设置属性值
public void setSchoolName(String schoolName){
this.schoolName = schoolName;
}
public void setStudentNumber(int studentNumber){
this.studentNumber = studentNumber;
}
public void setTeacherNumber(int teacherNumber){
this.teacherNumber = teacherNumber;
}
public void setClassNumber(int classNumber){
this.classNumber = classNumber;
}
public String getSchoolName() {
return schoolName;
}
public int getStudentNumber() {
return studentNumber;
}
public int getTeacherNumber() {
return teacherNumber;
}
public int getClassNumber() {
return classNumber;
}
public void show(){
this.schoolName = schoolName;
this.studentNumber = studentNumber;
this.teacherNumber = teacherNumber;
this.classNumber = classNumber;
System.out.println("1:" + schoolName + "2:"+ studentNumber + "3:" + teacherNumber + "4:" + classNumber);
}
public static void main(String[] args) {
School s1 = new School();
s1.schoolName = "南京邮电大学";
System.out.println("学校名为:" + s1.schoolName);
School s3 = new School();
s3.setSchoolName("南京大学");
s3.setStudentNumber(10000);
s3.setTeacherNumber(2000);
s3.setClassNumber(800);
s3.show();
String schoolName = s3.getSchoolName();
System.out.println(schoolName);
System.out.println(s3.getStudentNumber());
System.out.println(s3.getTeacherNumber());
System.out.println(s3.getClassNumber());
}
}
私有化后,多个对象之间的属性值交互的写法
public class Student {
//属性 学号、姓名、班级
private int sid;
private String sName;
private String sClass;
private String[] course;
//构造方法
public String[] getCourse() {
return course;
}
public void setCourse(String[] course) {
this.course = course;
}
public Student() {
}
public Student(int sid, String sName, String sClass) {
this.sid = sid;
this.sName = sName;
this.sClass = sClass;
}
//get/set方法
public int getSid() {
return sid;
}
public void setSid(int sid) {
this.sid = sid;
}
public String getsName() {
return sName;
}
public void setsName(String sName) {
this.sName = sName;
}
public String getsClass() {
return sClass;
}
public void setsClass(String sClass) {
this.sClass = sClass;
}
//将对象以字符串的形式输出
@Override
public String toString() {
return "Student{" +
"sid=" + sid +
", sName='" + sName + '\'' +
", sClass='" + sClass + '\'' +
", course=" + Arrays.toString(course) +
'}';
}
}
//课程类
public class Course {
private String name;
public Course(String name) {
this.name = name;
}
public Course() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
//测试类
public class StudentTest {
public static void main(String[] args) {
//创建student对象s1
Student s1 = new Student();
//s1调用set方法设置属性
s1.setsName("张三");
s1.setSid(1001);
s1.setsClass("1班");
//课程名称,需要从Course对象获取
//创建Course对象,并指定每个课程对象对应的课程名
Course c1 = new Course("语文");
Course c2 = new Course("数学");
Course c3 = new Course("英语");
//设置s1对象的课程,需要调用已知的课程对象的名称,放入课程数组中
//课程对象的名称,就得通过get方法来拿到
String[] course = {c1.getName(),c2.getName(),c3.getName()};
s1.setCourse(course);
//输出s1对象
System.out.println(s1);
}
}
包的引用,常用包
包:称为package,就是用来存放类的文件夹
一般在创建类的时候,一般在类文件的第一行出现,内容是这个类存在于项目中src这个目录下的所有路径
包的取名:一般包是以倒置公司的网络域名作为前缀,再加上项目名。包一般都使用的小写的名字
常用包:java.util java.sql java.io
导包:使用import关键字将包导入
导入相同的类名,不同包的类时候,需要使用其中一个包名作为前缀,用来区别不同的类
访问控制符
访问控制修饰符
Java中,访问控制修饰符,用来保护 类、变量、方法、构造方法被访问的情况
private :私有的,在同一个类中,是可以被调用的,不能用来修饰类
default :默认,什么都不写,在类的同一个包下可以被访问,可以修饰 : 类、变量、方法
protected:受保护的 ,同一个包下可以被访问,或者其子类都可以访问,不可以用来修饰类,可以用来修饰 变量、方法
public:公共的,所有位置都可以访问
非访问控制修饰符 static
常用的非访问修饰符 ,static、final 、 abstract 、synchronized 、volatile
static修饰符,表示静态的,可以用来修饰类中的 方法和变量,被static修饰后的方法称为类方法,被static修饰过的变量,称为类变量,还可以修饰代码块
static修饰成员变量
1,static修饰的属性,是类的所有对象共享的,可以用来在对象之间共享数据
2,将来如果类中所有的对象都包含一个相同属性值的变量,可以把这个属性定义为静态的,从而节省内存空间
public class Student {
String name;
int age;
static String className; //静态的属性,对象共享
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", className=" + className +
'}';
}
}
public class StaticDemo {
static int num;
public static void main(String[] args) {
num++;
StaticDemo s1 = new StaticDemo();
s1.num++;
StaticDemo s2 = new StaticDemo();
s2.num++;
StaticDemo.num++;
System.out.println(num); //4
}
}
static修饰成员方法
static修饰方法,随着类的加载而加载,比如main方法,优先于对象存在,即使没有创建这个类的对象,也可以通过类名调用类中的static方法,被类的所有对象共享
静态方法中,只能访问静态成员变量和 静态方法
public class StaticDemo01 {
//普通变量
int number01 = 100;
//静态变量
static int number02 = 200;
public void say(){
}
public static void show(){
//静态方法中,不能使用非静态的成员变量
//System.out.println(number01);
System.out.println(number02);
//静态方法中,也不能调用非静态的成员方法
//say();
}
//main方法也是静态方法
public static void main(String[] args) {
// say();
// System.out.println(number01);
System.out.println(number02);
show();
}
}
static修饰代码块
static修饰的代码块称为静态代码块
代码块是什么 ?
在Java中,使用{}括起来的代码,就被称为代码块。代码块分类如下 :
1,局部代码块:声明在局部位置,用于限定变量的生命周期
2,构造代码块:声明在类中的成员位置,一般在调用构造方法之前会执行构造代码块
3,静态代码块: 声明在类中的成员位置,多了static修饰符,一般类被加载的时候就会执行,只会执行一次
public class StaticDemo02 {
//静态代码块
static {
int a = 100;
System.out.println(a);
}
//构造代码块
{
int b = 200;
System.out.println(b);
}
public StaticDemo02(){
System.out.println("构造方法");
}
{
int c = 300;
System.out.println(c);
}
static {
int d = 400;
System.out.println(d);
}
}
public class StaticTest {
public static void main(String[] args) {
{
int e = 500;
System.out.println(e);
}
StaticDemo02 s1 = new StaticDemo02();
//500
//100
//400
//200
//300
//构造方法
System.out.println("----------------------");
StaticDemo02 s2 = new StaticDemo02();
//200
//300
//构造方法
}
}
继承的定义、继承的好处、如何继承、继承的特征
定义 :
把多个类中,相同的成员提取出来,定义到一个独立的类中。
然后让当前类和独立类之间产生关系,使当前类具有独立类中的成员内容,这种关系,称为继承
写法:
用extends 关键字来实现继承
class 子类名 extends 父类名{}
public class Person {
String name; //姓名
int age; //年龄
String gender; //性别
public void show(){
System.out.println("我的姓名:" + name
+ ",我的年龄:" + age
+ ",我的性别:" + gender);
}
}
public class Student extends Person {
String className; //班级
}
public class Emp extends Person{ //员工类
String deptName; //部门名称
}
public class Test {
public static void main(String[] args) {
Student s1 = new Student();
//调用来自Person中的属性
s1.name = "张三";
s1.age = 20;
s1.gender = "男";
//调用来自Person类中的方法
s1.show();
Emp emp = new Emp();
emp.name = "李四";
emp.age = 30;
emp.gender = "男";
emp.show();
}
}
继承的好处:
1,提高代码的复用性,也可以提高代码的维护性
2,继承让类与类之间产生了一个关系,是将来学习的多态的前提
继承的缺点 :
继承会让类的耦合性增强,这样父类改变后,就会影响跟他相关的类
打破封装性,子类可以通过super访问父类的构造方法,从而完成私有属性的赋值,也可以通过继承父类的get/set方法,完成 父类私有属性的赋值、调用
继承的其他特点:
1,Java中只能单继承,只能继承一个类
2,Java中可以多重继承
什么时候可以使用继承?
两个类之间 存在 : is a 的关系
public class Person {
private String name; //姓名
private int age; //年龄
private String gender; //性别
//父类的属性私有化之后,子类可以通过构造方法、get/set方法
//间接的访问到父类的私有属性
public Person(String name, int age, String gender) {
this.name = name;
this.age = age;
this.gender = gender;
}
public Person() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public void show(){
System.out.println("我的姓名:" + name
+ ",我的年龄:" + age
+ ",我的性别:" + gender);
}
}
public class Student extends Person{
String className; //班级
//如果想要使用父类的构造方法,必须在子类中定义自己的构造
//然后在通过特殊方法,super关键字,去访问父类的构造方法
public Student(String name, int age, String gender) {
//super表示父类的意思,super()表示访问父类的构造方法
super(name, age, gender);
}
public Student(){}
}
public class Test {
public static void main(String[] args) {
//如果父类的属性,私有化之后,那么就不能被直接继承
//父类属性私有化之后,创建子类对象,怎么使用父类的私有属性
//1,子类的构造方法通过super访问父类的构造方法之后,
//就可以被拿来实例化对象的时候赋值使用了
Student s2 = new Student("张三", 20, "男");
s2.show();
//2,子类调用从父类继承过来的 getter/setter方法,完成赋值和调用
Student s3 = new Student();
s3.setName("李四");
s3.setAge(20);
s3.setGender("男");
s3.show();
System.out.println(s3.getName());
}
}
继承之后的成员关系 :
1,成员变量
如果子类 成员变量名 和 父类成员变量名 不一样,子类调用的就是子类中的成员变量
如果子类 成员变量名 和父类的成员变量名 一样,子类调用的其实也是子类自己的成员变量
2,成员方法
子类的成员方法和父类的成员方法不一样,子类调用 就是调用自己的方法
子类的成员方法和父类的成员方法同名,子类调用的还是自己的 (先找自身,再找父类)
3,构造方法
子类会默认去访问父类的无参构造,如果父类没有无参构造,那么,会报错
如果报错(父类没有无参构造)怎么解决 ?
1,给父类加上无参构造
2,父类没有无参构造,那么必定存在其他的有参构造,子类通过super去访问父类的有参构造,这个时候,子类也只能 通过有参构造去创建对象
public class Person {
String name; //姓名
int age; //年龄
String gender; //性别
//父类的无参构造被注释,子类就无法使用父类的无参构造了
//public Person() {
//}
public Person(String name, int age, String gender) {
this.name = name;
this.age = age;
this.gender = gender;
}
public void show(){
System.out.println("我的姓名:" + name
+ ",我的年龄:" + age
+ ",我的性别:" + gender);
}
}
public class Student extends Person{
String name;
String className; //班级
//如果父类不提供无参构造,那么子类也不能使用无参构造
//public Student() {
//}
public Student(String name, int age, String gender, String name1, String className) {
super(name, age, gender);
this.name = name1;
this.className = className;
}
public void say(){
System.out.println("子类的say方法");
}
//public void show(){
// System.out.println("子类的show方法");
//}
}
public class Test {
public static void main(String[] args) {
Student s1 = new Student();
//子类指定了跟父类同名的属性,赋值的时候,
// 其实赋值的是自己子类中的属性
s1.name = "张三";
//调用来自Person中的属性
s1.age = 20;
s1.gender = "男";
s1.className = "1班";
//调用来自Person类中的方法
s1.show(); //我的姓名:null,我的年龄:20,我的性别:男
s1.say(); //自己调用和父类不同名方法,在自己类找
//s1.show(); //子类调用同名方法,优先调用自己
}
}
继承总结:
子类继承父类,被继承的类称为父类、超类、基类,可以继承父类的所有属性和方法(私有的可以间接的继承,不能直接访问)
Java中一个类只能继承一个类,可以多重继承,从而实现继承多个类的效果
如果创建了一个类,没有写继承,那么这个类其实是继承了Object类
子类可以扩展属性,方法
继承提升代码的复用性