虚拟世界模拟现实生活,必须保证模拟一致
对同一类事物的抽象的描述,也就是:不是具体的
如:电脑类、水杯类、键盘类、人类
万物皆对象,也就是说:具体的实例
我的电脑、张三的水杯
对象所做的事情称为方法或行为(不是属性)
第一步:编写类
语法格式:
[修饰符] class 类名{
}
第二步:编写属性
语法格式:
[修饰符] 数据类型 属性名称 [=值];
第三步:编写方法
语法格式:
[修饰符] 返回类型 方法名称([参数列表]){
方法体
}
也就是包含main方法的类
Test
创建对象也叫做实例化
语法格式:
类名 引用名称 = new 类名();
一个类可以创建N个对象
//第一步:编写类
class Student{
//第二步:编写属性也叫成员变量或实例(对象)变量,如果有属性类型相同建议分开写
String name;//默认值为null
int age;//默认值为0
char sex;//默认值为\u0000
String address;//默认值为null
//第三步:编写方法
public void study(){
System.out.println("正在学习面向对象课程。。。。");
}
}
访问对象的中的属性:
引用名称.属性名称
访问对象中的方法:
语法格式:引用名称.方法名称();
//第一步:编写类
class Student{
//第二步:编写属性也叫成员变量或实例(对象)变量,如果有属性类型相同建议分开写
String name;//默认值为null
int age;//默认值为0
char sex;//默认值为\u0000
String address;//默认值为null
//第三步:编写方法
public void study(){
System.out.println("正在学习面向对象课程。。。。");
}
}
//编写学生的测试类
class StudentTest{
public static void main(String[] args){
//根据类来创建对象,右侧对象地址赋给引用名称zs
Student zs = new Student();//创建Student对象,同时在堆内存中开辟一块空间
//通过引用名称zs获取对象中的属性
System.out.println(zs.sex);
//对对象的属性进行赋值,如:引用名称.属性名称 = 值
zs.name = "张三";
zs.age = 19;
zs.sex = '男';
zs.address = "北京市大兴区";
//输出引用名称zs对应对象中所有属性的值
System.out.println("姓名:"+zs.name+"\n年龄"+zs.age+"\n性别"+zs.sex+"\n地址"+zs.address);
//使用引用名称访问对象中的方法,语法格式:引用名称.方法名称();
zs.study();
//创建第二个学生对象
Student s = new Student();
System.out.println(s.name);
s.study();
}
}
综合案例:
/**
* 编写电脑类,属性:品牌、颜色、价格。方法:显示电脑信息
* 编写电脑测试类,创建电脑对象,输出电脑信息
*/
class Computer{
//属性也叫成员变量或者实例变量
String brand;//null
String color;//null
double price;//0.0
//方法
public void show(){
//注意本类中的成员变量可以在本类中任意位置直接使用
System.out.println("品牌:"+brand+"\n颜色:"+color+"\n价格:"+price);
}
}
//编写电脑测试类
class ComputerTest{
public static void main(String[] args){
//创建电脑对象也叫实例化
Computer c = new Computer();
//对引用名称中所有的属性进行赋值
c.brand = "Lenovo";
c.color = "black";
c.price = 4999.9;
c.show();
}
}
/*
* 编写车类,属性:颜色、品牌、价格
* 编写车的测试类,创建车的对象
*/
class Car{
//属性也叫成员变量
String color;
String brand;
int price;
//方法
public void print(String name){//name是形参,也属于局部变量
int i;//i就是局部变量
for(int j = 1;j<=5;j++){//j也属于局部变量
}
}
public void show(){
int a;//a是局部变量
//System.out.println("a = "+a);//出现编译错误,原因是局部变量必须先声明再赋值最后才使用
a = 123;
System.out.println("a = "+a);
System.out.println("price = "+price);//0
}
public void print2(){
//同一个类中,成员变量的名字可以和局部变量的名字同名,但是局部变量名字优先,也就是就近的优先
//如果非要访问成员变量,必须加this.
String color = "灰色";//color是局部变量
System.out.println("输出局部变量color的值:"+color);
System.out.println("输出成员变量color的值:"+this.color);
//this代表当前这个对象,也就是当前谁(c)调用这个方法则这个对象就是谁
}
public void setBrand(String brand){//brand是形参,属于局部变量
//将局部变量brand的值赋给成员变量brand
this.brand = brand;
}
}
//编写车的测试类
class CarTest{
public static void main(String[] args){
//实例化车
Car c = new Car();
c.print2();//灰色
Car c3 = new Car();
c3.setBrand("大众");
System.out.println("品牌:"+c3.brand);
}
}
作用:完成对对象的属性赋值
构造方法:
构造方法是一种特殊的方法,构造方法名字必须与类名一致
构造方法没有返回类型,也就是不编写类型
语法格式:public 方法名称([参数列表]){}
构造方法时如何执行的?
当创建对象时自动执行匹配的构造方法
构造方法分类
隐式构造方法:
当在一个类中,没有手动编写构造方法,则系统会提供一个默认的无参的构造方法,即一个构造也没写
显式构造方法:
当在一个类中,手动编写构造方法,则系统不会提供默认的无参的构造方法
建议当手动编写构造方法时,先编写无参构造方法,然后再编写需要的构造方法
构造方法重载
在同一个类中,构造方法的名字必须相同,参数列表不同(个数、类型、顺序不同)
/*
* 编写狗类,属性:品种、颜色、名字、年龄、性别
* 方法:输出狗的信息
* 编写狗的测试类,实例化狗,调用狗的方法输出信息
* */
class Dog{
//构造方法
public Dog(){//无参
//完成对品种、颜色、名字、年龄、性别
strain = "土狗";
color = "黑色";
name = "旺财";
age = 5;
sex = '公';
}
//带参构造方法,完成对属性品种、颜色、名字
public Dog(String strain,String color,String name){
//完成局部变量的值,赋给成员变量
this.strain = strain;
this.color = color;
this.name = name;
}
//编写对所有属性的构造方法
public Dog(String strain,String color,String name,int age,char sex){
this.strain = strain;
this.color = color;
this.name = name;
this.age = age;
this.sex = sex;
}
//这是普通的方法,不是构造方法
public void Dog(String name){
this.name = name;
}
//属性也叫成员变量
String strain;
String color;
String name;
int age;
char sex;
//方法:输出狗的信息
public void print(){
System.out.println("品种:"+ strain +"\n颜色:"+color+"\n名字:"+name+"\n年龄:"+age+"\n性别:"+sex);
}
}
//编写狗的测试类
class DogTest{
public static void main(String[] args){
//实例化狗
Dog d = new Dog();
//第一种方法:完成对对象中的属性赋值:“引用名称.属性名称 = 值”
d.strain = "拉布拉多犬";
d.color = "黄色";
d.name = "小黄";
d.age = 3;
d.sex = '公';
d.print();
//第二种方法:完成对对象中的属性赋值,使用构造方法完成
/*Dog d2 = new Dog();
d2.print();
System.out.println("--------------------");
Dog d3 = new Dog();
d3.print();*/
//创建Dog对象同时执行带三个参数的构造方法
Dog d4 = new Dog("泰迪","棕色","小迪");
d4.print();
//创建对象同时对所有属性赋值
Dog d5 = new Dog("哈士奇","白色","二哈",4,'公');
d5.print();
}
}
//第一步:编写类
class Student{
//属性
String name;
int age;
//方法
public void print(){
System.out.println("名字:"+name+"\n年龄:"+age);
}
}
//编写学生的测试类
class StudentTest{
public static void main(String[] args){
//创建学生对象
//Student s = new Student();
//将上一条语句编写为如下两条语句
Student s;//声明了一个局部变量s,也叫做引用名称s,当前s是Student类型,Student类型是用户自定义的类作为类型
s = new Student();
s = new Student();
s = new Student();
s = null;
s.print();
//int i = 10;
int i;//i是局部变量,并且是整数类型
i = 10;
i = 123;
}
}
//第一步:编写类
class Student{
//属性
String name;
int age;
//方法
public void print(){
System.out.println("名字:"+name+"\n年龄:"+age);
}
}
//编写学生的测试类
class StudentTest{
public static void main(String[] args){
Student s;
s = new Student();
s.print();
s = new Student();
s.name = "张三";
s.print();
s = null;//s不能.age.name了
//s.print();//出现运行错误,错误是空指针异常,
//原因:引用名称s是null,因此不能访问每个对象中的属性或方法,如果非要访问就会出现空指针异常
//解决办法:在调用某个对象中的属性或办法时,必须保证该引用名称中存放对象的地址
s = new Student();
s.print();
}
}
/*
* 编程完成如下要求:
* 班级类:
* 属性:编号,名称,地址
* 定义:无参构造方法,有参构造方法
* 定义方法:显示班级信息
* 学生类:
* 属性:学号,姓名,性别,年龄,所在班级
* 定义方法:显示学生的信息(学号,姓名,性别,年龄,班级编号,班级名称)
*
* 注意:所在班级应为班级类的类型
* 测试类:
* 通过有参构造方法,创建班级对象
* 通过无参构造方法,创建学生类对象
* 调用显示信息的方法显示学生的信息
*
* */
//编写班级类
class Grade{
//属性:编号,名称,地址
int num;
String name;
String address;
//构造方法
public Grade(){
}//无参构造方法
public Grade(int num,String name,String address){
this.num = num;
this.name = name;
this.address = address;
}
//方法:显示班级信息
public void show(){
System.out.println("班级编号:"+num+"\n班级名称:"+name+"\n班级地址:"+address);
}
}
//编写学生类
class Students{
//属性:学号,姓名,性别,年龄,所在班级
int id;
String name;
char sex;
int age;
Grade grade = new Grade();//grade是类中声明的成员变量,也叫局部变量,Grade类型
//注意grade没有赋值时则默认值为null
//方法:显示学生的信息(学号,姓名,性别,年龄,班级编号,班级名称)
public void showInfo(){
System.out.println("学生信息如下:");
System.out.println("学号:"+ id+"\n姓名:"+name+"\n性别:"+sex+"\n年龄:"+age+
"\n班级编号:"+grade.num+"\n班级名称:"+grade.name);
}
}
//测试类
class Test{
public static void main(String[] args){
//通过有参构造方法,创建班级对象
Grade grade = new Grade(431,"java基础班","四楼四教室");
//通过无参构造方法,创建学生类对象
Students s = new Students();
//调用显示信息的方法显示学生的信息
s.showInfo();
}
}
封装、继承和多态
定义:
隐藏类的内部信息,不允许外部程序员直接访问,而是通过方法进行操作
封装操作步骤:
//第一步:编写类
class Student{
//属性
String name;
//第一步:将属性设置为私有的private,只能在本类中使用
private int age;
char sex;
//第二步:编写对应属性的赋值setXxx和取值getXxx方法
public void setAge(int age){
//第三步:根据情况编写判断语句
//将局部变量的值赋给成员变量,年龄0-100,否则为18
if(age >= 0 && age <=100){
this.age = age;
}else{
this.age = 18;
}
}
public int getAge(){
return age;//表示返回成员变量age的值
}
}
//编写学生的测试类
class StudentTest{
public static void main(String[] args){
Student s;
s = new Student();
s.name = "张三";
/*运行时发现有些属性如年龄性别不符合实际意义
* 解决办法:赋值之前进行判断,当前值如果合法则进行赋值,否则不赋值,称为封装
* */
s.setAge(12345);
System.out.println("\n年龄:"+s.getAge());
}
}
封装综合案例:
/*
* 编写学生类,属性:名字、年龄、性别
* 要求:使用封装完成,对所有属性进行赋值和取值
* 年龄:1-120,否则19
* 性别:男、女,否则男
* */
class Student1{
//属性:
private String name;
private int age;
private char sex;
//编写所有属性的赋值setXxx
public void setName(String name){
this.name = name;
}
public void setAge(int age){
//判断1-120
if(age >= 1 && age <=120){
this.age = age;
}else{
this.age = 19;
}
}
public void setSex(char sex){
//判断性别为男、女
if(sex == '男' || sex == '女'){
this.sex = sex;
}else{
this.sex = '男';
}
}
//编写所有属性的赋值getXxx
public String getName(){
return name;
}
public int getAge(){
return age;
}
public char getSex(){
return sex;
}
}
//编写测试类
class Student1Test{
public static void main(String[] args){
//创建学生对象
Student1 s = new Student1();
//对所有属性赋值
s.setName("李四");
s.setAge(1234);
s.setSex('a');
//输出引用名称s中所有属性的值
System.out.println("姓名:"+s.getName()+"\n年龄:"+s.getAge()+"\n性别:"+s.getSex());
}
}
/*
编写车类,属性:车牌号、颜色、价格,方法:输出车的信息
编写车的测试类,创建车的对象,输出车的信息
*/
class Car{
//构造方法
public Car(){
}
//带参构造方法,完成对id和price赋值
public Car(String id,int price){
this.id = id;
this.price = price;
}
//编写对所有属性赋值的构造方法
/*public Car(String id,String color,int price){
this.id = id;
this.color = color;
this.price = price;
}*/
//编写第二种带三个参数赋值的构造方法
public Car(String id,String color,int price){
//将局部变量id和price的值,给带两个参数的构造方法赋值
this(id,price);//必须在构造方法中的第一个语句,构造方法不能自己调用自己
this.color = color;
//this(id,color,price);//构造方法不能出现递归调用
}
//属性
String id;
String color;
int price;
//方法
public void print(){
//在本类的方法中,可以直接访问本类中的成员变量(属性)
//System.out.println("车牌号:"+id+"\n颜色:"+color+"\n价格:"+price);
//上一条语句可以编写为如下:
System.out.println("车牌号:"+this.id+"\n颜色:"+this.color+"\n价格:"+this.price);
}
public void print2(String id){//id是形参,属于局部变量
System.out.println("输出成员变量id:"+this.id);
}
public void print3(){
//调用本类中的print方法,可以直接使用:方法名称([参数列表]);
print();//等价于this.print()
}
}
//编写测试类
class CarTest{
public static void main(String[] args){
//实例化车
Car c = new Car();
c.print();
//System.out.println(this.id);//编译错误,因为this只能在本类(当前类)中使用
Car car = new Car();
car.print();//this就是car即当前调用这个方法的对象
Car c3 = new Car();
c3.print3();
//创建对象同时执行带两个参数的构造方法
Car c4 = new Car("京A88888",800000);
c4.print();
Car c5 = new Car("沪C55555","黄色",5000000);
c5.print();
}
}
传递的是真正的值,在一个方法中改变本类的值,对另一个方法中变量的值没有任何影响,各自变量是独立的
class Method01{
public static void swap(double a,double b){
double t = a;
a = b;
b = t;
System.out.println(a);
System.out.println(b);
}
public static void change(int x,int y){
x += 5;
y += 10;
System.out.println("x="+x);
System.out.println("y="+y);
}
public static void main(String[] args){
int x = 10,y = 20;
System.out.println("x:"+x);//x:10
System.out.println("y:"+y);//y:20
change(x,y);//x=15 y=30.弹栈了,xy不在了
System.out.println("x的值:"+x);//x的值:10
System.out.println("y的值:"+y);//y的值:20
double num1 = 3.4,num2 = 10.6;
swap(num1,num2);//10.6 3.4
//System.out.println(a);//报错
System.out.println(num1);//3.4
System.out.println(num2);//10.6
}
}
传递的是地址,也就是说多个引用名称共用一个对象
class Student{
//属性
String name;
int age;
//构造方法
public Student(){
}
public Student(String name,int age){
this.name = name;
this.age = age;
}
}
//编写学生测试类
class StudentTest{
public static void main(String[] args){
//实例化学生
Student s = new Student("张三",19);
Student s2;//在main方法中声明,局部变量
s2 = s;//s和s2共用同一个地址,也就是说s和s2引用名称指向一个对象
System.out.println("s2.name="+s2.name);//s2.name=张三
System.out.println("s2.age = "+s2.age);//s2.age = 19
s2.name = "李四";
System.out.println("s2.name = "+s2.name);//李四
System.out.println("s.name = "+s2.name);//李四
}
}
class Student{
//属性
String name;
int age;
//构造方法
public Student(){
}
public Student(String name,int age){
this.name = name;
this.age = age;
}
}
//编写学生测试类
class StudentTest{
public static void change(Student s){
System.out.println(s.name);
System.out.println(s.age);
s.name = "无名氏";
}
public static void main(String[] args){
Student s = new Student("李四",23);
System.out.println(s.name);//李四
System.out.println(s.age);//23
change(s);
System.out.println(s.name);//无名氏
}
}
/*
* 编写学生类,属性:名字、现住址(北京)
* */
class Student1{
//构造方法
public Student1(){
}
public Student1(String name){
this.name = name;
}
//属性
String name;//称为非静态属性,也叫做实例变量
static String address = "北京";//称为静态属性也叫类的变量
}
//编写学生测试类
class Student1Test{
public static void main(String[] args){
//创建对象
Student1 s= new Student1();
Student1 s2 = new Student1("张三");
System.out.println(Student1.address);//静态属性与类同生死
System.out.println(s.name);
System.out.println(s.address);
}
}
class Student1{
//构造方法
public Student1(){
}
public Student1(String name){
this.name = name;
}
//属性
String name;
static String address = "北京";
//称为静态方法也叫类的方法
public static void print2(){
}
public static void print(){
System.out.println("执行了print方法");
//System.out.println(name);//静态方法中只能访问静态属性、静态方法
System.out.println(address);
print2();
}
//称为非静态方法也叫实例方法
public void show(){
System.out.println("执行了show方法");
}
}
//编写学生测试类
class Student1Test{
public static void main(String[] args){
Student1.print();//执行了print方法
Student1 s1 = new Student1();
System.out.println(s1.name);//null
s1.show();//执行了show方法
s1.print();//执行了print方法
s1 = null;
//s1.show();//出现运行错误,因为对象不存在
s1.print();//执行了print方法
}
}
编写狗类,属性:名字、年龄、品种、颜色,方法:显示信息
编写猫类,属性:名字、颜色、性别、年龄,方法:显示信息
编写测试类,创建猫和狗的对象,并分别显示信息
分析得到:
如果多个类中有相同属性和方法,能否单独编写一个类?----》能
解决办法:
动物类:
属性:名字、年龄、颜色
方法:显示信息
狗类,继承,动物类
独有属性:品种
猫类,继承,动物类
独有属性:性别
减少代码的冗余性
[修饰符] class 类名{
//属性和方法
}
[修饰符] class 子类类名 extends 父类类名{
//编写独有属性和方法
}
注意:
class Animal{
//属性
String name;
int age;
String color;
//方法:显示信息
public void show(){
System.out.println("名字:"+name+"\n年龄:"+age+"\n颜色:"+color);
}
}
//编写狗的子类继承动物父类
class Dog extends Animal{
//编写子类中独有属性和方法
String strain;
}
//编写猫的子类并继承动物父类
class Cat extends Animal{
//编写子类中独有属性:性别
char sex;
}
class A {
//编写2个属性2个方法
}
class B extends A{
//独有属性1个,方法3个 # B里3个属性5个方法
}
class C extends A{
//编写独有属性1
}
class D extends B{
# D继承B里3个属性5个方法
}
override也叫做覆盖
class Animal{
//属性
String name;
int age;
String color;
//方法:显示信息
public void show(){
System.out.println("名字:"+name+"\n年龄:"+age+"\n颜色:"+color);
}
public Object getInfo(){
return null;
}
}
//编写狗的子类继承动物父类
class Dog extends Animal{
//编写子类中独有属性和方法
String strain;
//重写也叫覆盖override:在子类中重写父类的方法,必须与父类的方法名称一致、参数列表一致、返回类型一致、修饰符一致
public void show(){
//在子类中可以直接访问父类中的属性(前提:父类中属性没有使用private修饰)
System.out.println("名字:"+name+"\n年龄:"+age+"\n颜色:"+color+"\n品种:"+strain);
}
//重写父类的getInfo方法
public String getInfo(){
return "OK";
}
}
//编写猫的子类并继承动物父类
class Cat extends Animal{
//编写子类中独有属性:性别
char sex;
}
//编写测试类
class Test{
public static void main(String[] args){
//创建狗的对象
Dog d = new Dog();
//显示信息
d.show();//先在Dog类中找show方法,如果没有找到则到父类中找
}
}