类:
1.定义一个类的语法格式:
[修饰符列表] class 类名{
类名 = 属性 + 方法
//属性(实例变量),描述的是状态
//方法 ,描述的是行为动作
}
2.为什么要定义类?
因为要通过类实例化对象。有了对象,让对象和对象之间协作起来形成系统
3.一个类可以实例化多个java对象。(通过一个类可以造出多个java对象)
public class Student {
// 属性:姓名 年龄 性别
// 姓名
String name;
// 年龄
int age;
// 性别
boolean gender;
}
public class StudentTest01 {
public static void main(String[] args) {
//通过学生类Student实例化学生对象(通过类创造对象)
//Student s1;是什么,s1是变量名。Student是一种数据类型名。属于引用数据类型。
Student s1 = new Student();
//访问对象属性
System.out.println("姓名:" + s1.name);
System.out.println("年龄:" + s1.age);
System.out.println("性别:" + s1.gender);
s1.name = "张三";
s1.age = 20;
s1.gender = true;
System.out.println("姓名:" + s1.name);
System.out.println("年龄:" + s1.age);
System.out.println("性别:" + (s1.gender ? "男" : "女"));
}
}
package com.powernode.javase.oop05;
public class Student {
String name;
//this 本质上是引用
//this 中保存的也是对象地址
//this 中保存的是当前对象的内存地址
public void Study(){
System.out.println(this.name + "正在努力学习!");
}
}
package com.powernode.javase.oop05;
public class StudentTest {
public static void main(String[] args) {
Student zhangsan = new Student();
zhangsan.name = "张三";
System.out.println("学生姓名:" + zhangsan.name);
zhangsan.Study();
Student lisi = new Student();
lisi.name = "李四";
System.out.println("学生姓名: " + lisi.name);
lisi.Study();
}
}
package com.powernode.javase.oop07;
/*
* 为保证User类型对象的安全我,我们需要使用封装机制。实现封装的步骤是什么?
* 第一步:属性私有化。(什么事私有化?使用private进行修饰)
* 属性私有化的作用是:禁止外部程序对该属性进行随意的访问
* 所有被private修饰的,都是私有的,私有的只能在本类中访问
*
* 第二步:为了保证外部的程序仍然能够访问age属性,所以就为外部程序提供公开的访问入口
* 访问一般分两种:
* 读:读取属性的值
* 改:修改属性的值
* 那么应该对外提供两个方法,一个负责读,一个负责改
* 读方法的格式:getter
* public int getAge(){}
* 改方法的格式:setter
* public void setAge(int age){}
* */
public class User {
private int age;
public int getAge(){
return age;
}
public void setAge(int num){
// this.age = num;
if (num < 0 || num >100){
System.out.println("对不起,你的输入不合法!");
return;
}
}
}
package com.powernode.javase.oop07;
public class UserTest {
public static void main(String[] args) {
User u = new User();
// int age = u.getAge();
// System.out.println("年龄 ;" + age);
System.out.println("年龄 ;" + u.getAge());
u.setAge(-100);
System.out.println("年龄 ;" + u.getAge());
}
}
package com.powernode.javase.oop09;
public class ConstructorTest01 {
public static void main(String[] args) {
/*
* 调用Student类的构造方法来完成Student类型对象的创建
* 一下代码的本质上:通过new运算符调用无参数的构造方法来完成对象的实例化
* s1是一个引用。保存了内存地址指向了堆内存当中的Student类型的对象
* 这样就完成了学生类对象的创建及初始化
* 无参数构造方法没有给属性手动赋值,但是系统会附默认值
* */
Student s1 = new Student();
System.out.println(s1.getAddress());
System.out.println(s1.getAge());
System.out.println(s1.isSex() ? "男" : "女");
System.out.println(s1.getAddress());
}
}
构造方法/Constructor/构造器
1.构造方法有什么用
作用1:对象的创建(通过调用构造方法可以完成对象的创建)
作用2.对象的初始化(给对象的所有属性赋值就是对象的初始化)`
2.怎么定义构造方法
[修饰符列表] 构造方法名(形参列表){
构造方法体;
}
注意:构造方法名必须和类名一致。 构造方法不需要提供返回值类型
3.构造方法怎么调用
使用new运算符来调用
语法:
new 构造方法名(实参);
注意:构造方法最终执行结束后,会自动将创建的对象的内存地址返回。但是构造方法中不需要提供“return 值;”这样的语句
4.在java语言中,如果一个类没有显示的定义一个构造方法,系统会默认生成一个无参数的构造方法(通常把这个构造方法叫做缺省构造器)
5.一个类中如果显示的创造了构造方法,系统则不在提供缺省构造器。所以,为了对象创建更加方便,建议把无参数的构造方法手动写出来
6.在java中,一个类可以定义多个构造方法,而且这些构造方法自动构成方法重载(overload)
7.构造方法中给属性赋值了,为什么还要单独定义set方法给属性值呢?`
`在构造函数中赋值是对象第一次创建时属性赋的值。set方法可以在后期的时候调用,来完成属性值的修改`
8.构造方法执行原理?
构造方法执行包括两个阶段:
第一阶段:对象的创建
第二阶段:对象的初始化
对象在什么时候创建的?
new的时候,会直接在堆内存中开辟空间,然后给所有的属性默认值,完成对象的创建。(这个过程是在构造方法执行之前就完成了)
对象初始化在什么时候完成的?
构造方法开始执行,标志者开始进行对象的初始化。构造方法体执行完毕,表示对象初始化完毕。
9.构造代码块?
构造代码块什么时候执行,执行几次
构造代码块是在构造方法之前执行的
10.构造代码块有什么用 如果构造方法在最开始的时候,有相同的部分那就提取到构造方法中,可以提高代码的复用性和简洁性
package com.powernode.javase.oop09;
public class Student {
/*
* 姓名
* */
private String name;
/*
* 年龄
* */
private int age;
/*
* 性别
* */
private boolean sex;
/*
* 家庭住址
* */
private String address;
//无参数构造器
public Student(){
{
System.out.println("构造代码块执行了");
}
}
public Student(String name, int age, boolean sex, String address){
this.name = name;
this.address = address;
this.age = age;
this.address = address;
}
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 boolean isSex() {
return sex;
}
public void setSex(boolean sex) {
this.sex = sex;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
static关键字:
1.static翻译为静态的
2.static修饰的变量:静态变量
3.static修饰的方法:静态方法
4.所有的static修饰的,访问的时候,直接采用“类名.”,不需要new对象
5.什么情况下吧成员变量定义为静态成员变量?
当一个属性是对象级别的,这个属性通常定义为实例变量(实例变量是一个对象一份。100个人就有100份空间)
Static 还可以定义静态代码块:
1.语法:
static {
}
2.静态代码块什么时候执行?执行几次
静态代码块在类加载时执行,并且只执行一次
3.静态代码块可以编写多个,并且遵循自上而下的顺序执行
4.静态代码块什么时候用?
本质上就是为了程序员预留的一个特殊的时间节点:类加载时刻
如果你需要在类加载时刻执行一段代码的话,这段代码就可以写到静态代码块中
Singleton单例
单例模式怎么实现?
第一步:构造方法私有化;
第二步:对外提供一个公开的静态的方法,用这个方法获取单个实例
第三步:定义一个静态变量,在类加载的时候,初始化静态变量(只初始化一次)
饿汉式单例模式:类加载时对象就创建好了。不管对象用不用,提前吧对象创建好
package com.powernode.javase.oop14;
public class Singleton {
//定义的静态变量
private static Singleton s = new Singleton();
//构造方法私有化
private Singleton(){
}
//对外提供的公开的静态方法
public static Singleton get(){
return s;
}
}
package com.powernode.javase.opp17;
/**
* 人类
*
* 继承:
* 特征:
* 1.代码复用
* 2.有了继承,才有了方法覆盖和多态机制
*/
public class Person {
private String name;
private int age;
private String sex;
public Person(String name, int age, String sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
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 getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public void eat(){
System.out.println(this.getName() + "正在吃饭");
}
public void sleep(){
System.out.println(this.getName() + "正在睡觉");
}
}
package com.powernode.javase.opp17;
public class Teacher {
public String name;
public int age;
public String sex;
public Teacher(String name, int age, String sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
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 getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public void eat() {
System.out.println(this.getName() + "吃饭");
}
public void sleep() {
System.out.println(this.getName() + "睡觉");
}
}
package com.powernode.javase.opp17;
public class Test01 {
public static void main(String[] args) {
Person p = new Person("张三", 18, "男");
p.eat();
Teacher t = new Teacher("李老师", 45, "女");
t.eat();
}
}
回顾方法重载
1.什么时候考虑方法重载?
在一个类中,如果功能相似,可以考虑使用方法重载
这样做的目的是:代码美观,方便编程
2.当满足什么条件的时候满足构成方法重载?
1.在同一个类中
2.相同的方法名
3.不同的参数列表:顺序,个数,数据类型
3.方法重载机制属于编译阶段的功能(方法重载机制是给编译器看的)
方法覆盖/overrride/方法重写/overwrite
1.什么时候考虑方法重写?
当从父类中继承过来的方法,不能满足需求时,考虑方法重写
2.当满足什么条件的时候,构成方法重写?
条件1:方法堵盖发生在具有父子关系的父子类之间
条件2:具有相同的方法名
条件3.具有相同的形参列表
条件4.具有相同的返回值
3.关于方法覆盖的细节:
3.1当子类将父类方法继承后,将来子类对象调用方法的时候,一定执行重写之后的方法
3.2在java语言中,有一个注解,这个注解是专门用于在编译阶段检查这个放发是否重写了父类的方法
@Override是jdk5引入的,用于标注方法,被注解的方法必须是重写父类的方法,如果不是重写的方法,编译器会报错
@Override注解只在编译阶段有用,和运行期无关
3.3:如果返回值类型是引用类型,那么这个返回值类型可以是原类型的子类型
3.4:访问权限不能变低,但可以变高
3.5:抛出异常可以变多,但可以变少
3.6:私有的方法,以及构造方法不能继承,因此他们不存在方法重写
3.7:方法覆盖针对的是实例方法。和静态方法无关
package com.powernode.javase.opp19;
public class OverrideTest {
public static void main(String[] args) {
//创建小鸟对象
Bird b = new Bird();
b.eat();
b.move();
}
}
package com.powernode.javase.opp19;
public class Animal {
public void move()
{
System.out.println("动物移动");
}
public void eat()
{
System.out.println("吃吃吃");
}
}
package com.powernode.javase.opp19;
public class Bird extends Animal{
/**
* Brid对继承过来的move()方法不满意
* Bird类有权将move()方法覆盖掉/重写
*/
@Override
public void move(){
System.out.println("鸟儿在飞翔");
}
}