第十一章 类与对象详解
1.作业回顾
1,定义一个类Dog,它有age,name,color,String type。创建出来三个对象,赋值,并访问。
public class Dog {
//1,定义一个类Dog,它有age,name,color,String type。创建出来三个对象,赋值,并访问。
int age;
String name;
String color;
String type;
}
public static void main(String[] args) {
//1,定义一个类Dog,它有age,name,color,String type。创建出来三个对象,赋值,并访问。
Dog dog1 = new Dog();
dog1.name = "小狗1";
dog1.age = 1;
dog1.color = "灰色";
dog1.type = "哈士奇";
Dog dog2 = new Dog();
dog2.name = "小狗2";
dog2.age = 2;
dog2.color = "白色";
dog2.type = "萨摩耶";
Dog dog3 = new Dog();
dog3.name = "小狗3";
dog3.age = 3;
dog3.color = "灰色";
dog3.type = "中华田园犬";
System.out.println(dog1.name); //小狗1
System.out.println(dog2.age); //2
System.out.println(dog3.type); //中华田园犬
}
}
2.成员方法
java中不存在全局方法,所有的方法都是成员方法。成员方法分为两种:
类方法(使用static修饰的方法),实例方法(不使用static修饰的方法)。
类方法通过类名调用,实例方法通过对象调用。
public class Person {
String name; //实例变量
char gender; //实例变量
int age; //实例变量
static int count; //类变量
//实例方法
//实例方法可以操作调用此方法的对象的实例属性
public void showInfo() {
System.out.println("我叫:" + name);
System.out.println("我的性别是" + gender);
System.out.println("我的年龄是" + age);
System.out.println("有" + count + "对象");
}
//类方法
//类方法用于操作类变量
public static void setCount(int newCount) {
count = newCount;
//类方法不能访问实例变量
// System.out.println(name); //编译错误
}
//类方法
//类方法用于操作类变量
public static int getCount() {
return count;
}
}
public class Day112 {
public static void main(String[] args) {
Person p1 = new Person();
p1.name = "张三";
p1.gender = '男';
p1.age = 20;
Person.setCount(1); //通过类名调用类方法
p1.showInfo(); //通过对象调用实例方法
Person p2 = new Person();
p2.name = "李四";
p2.gender = '女';
p2.age = 21;
Person.setCount(Person.getCount() + 1); //通过类名调用类方法
p2.showInfo(); //通过对象调用实例方法
System.out.println("有" + Person.getCount() + "个对象"); //2
}
}
public class Day113 {
public static void main(String[] args) {
//类方法是属于类的,使用类方法,不必事先创建对象
Person.setCount(0);
}
}
3.构造器
public class Student {
//默认的无参构造器就是下面的构造器
// public Student() {
//
// }
String name;
int age;
//如果提供了一个构造器,那么编译器就不会提供默认的构造器了
//构造器的名称必须和类的名称相同
//构造器没有返回值,并且不使用void
public Student() {
System.out.println("Student构造器");
}
//构造器可以重载
//构造器可以有参数
//构造器用于初始化对象
public Student(String newName, int newAge) {
name = newName;
age = newAge;
}
}
public class Day114 {
public static void main(String[] args) {
//当使用new操作符创建类的一个实例时,构造器会被调用
//没有构造器不能创建对象,如果没构造器,编译器会提供一个默认的无参构造器
Student p1 = new Student();
Student p2 = new Student();
System.out.println(p1); //day11.Student@2401f4c3
System.out.println(p2); //day11.Student@7637f22
//调用有参构造器
Student p3 = new Student("张三", 10);
Student p4 = new Student("李四", 11);
System.out.println(p3.name); //张三
System.out.println(p4.age); //11
}
}
4.this关键字
每一个实例方法和构造器都有一个隐式参数this。
在实例方法中,this代表调用此方法的对象,在构造器中this代表当前被创建的对象。
public class Teacher {
String name;
int age;
public Teacher(String name, int age) {
//调用构造器时,对象还没有被创建出来
//在构造器中this代表当前被创建的对象
this.name = name;
this.age = age;
System.out.println(this);
}
public void setName(String newName) {
//给调用此方法的对象的name属性赋值
//name = newName;
//在实例方法中,this代表调用此方法的对象
this.name = newName;
System.out.println(this);
}
public void setAge(int age) {
// age = age; //无法给对象的age属性赋值
this.age = age;
}
}
public class Day115 {
public static void main(String[] args) {
Teacher t1 = new Teacher("李四", 21);
System.out.println(t1); //day11.Teacher@2401f4c3
t1.setName("张三");
System.out.println(t1.name); //张三
t1.setAge(20);
System.out.println(t1.age); //20
System.out.println(t1); //day11.Teacher@2401f4c3
}
}
使用this,构造器可以调用构造器。
public class Animal {
String name;
int age;
String type;
public Animal(String name) {
this.name = name;
}
public Animal(String name, int age) {
//调用上面的构造器
this(name);
this.age = age;
}
public Animal(String name, int age, String type) {
//调用上面的构造器
this(name, age);
this.type = type;
}
}
public class Day116 {
public static void main(String[] args) {
Animal a1 = new Animal("小鸟1", 1, "麻雀");
System.out.println(a1.name);
System.out.println(a1.age);
System.out.println(a1.type);
}
}
5.包和导入
在项目开发中类的名字必须是唯一的。可以使用包来把类组织起来。包类似于文件夹,把类放到不同的包下,就可以避免命名冲突。
java标准库中有很多包,这些包都是按照功能来划分的。java.lang包(包括了java中最基础的类,java.lang包中的类是不需要导入的),java.util包(包括了java工具类),java.net包(包括了java网络相关的类)。
Arrays类位于java.util包中,那么它的全名就是java.util.Arrays。
package a; //指示这个类位于a包下,注意与实际文件的层次匹配
//package b; //编译错误
public class Foo {
}
public class Foo {
public static void main(String[] args) {
//必须使用全名,在b包的Foo类中调用a包的Foo类
a.Foo f = new a.Foo();
}
}
//import a.Foo;
import a.*; //导入a包中的所有类(不推荐)
public class Day117 {
public static void main(String[] args) {
// a.Foo f = new a.Foo();
Foo f = new Foo();
Math.max(1, 2);
}
}
6.访问权限修饰符
6.1类的访问权限
类可以使用public关键字修饰,指示这个类是公有的,可以被其他无关类访问(包括同一个包下的和不同包下的类)。
如果不加修饰符,则认为这个类是默认访问权限(包访问权限),可以被同一个包下的无关类访问。
6.2成员变量和成员方法的的访问权限
本类 | 同一包下的无关类 | 不同包下(子类) | 不同包下(无关类) | |
---|---|---|---|---|
private | Y | |||
default | Y | Y | ||
protected | Y | Y | Y | |
public | Y | Y | Y | Y |
protected包括包访问权限和子类访问权限。
7.数据封装
隐藏对象内部的数据,并要求通过方法执行所有的交互称为数据封装。
把所有的属性设置为private的,并且提供getter和setter方法。避免外部直接访问和修改实例变量,保护数据的合法性。
public class Child {
private String name;
private int age;
//alt + shift + s 选择Generate Getters and Setters
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 <= 0 || age >= 150) {
System.out.println("年龄非法");
return; //退出当前方法
}
this.age = age;
}
}
public class Day1110 {
public static void main(String[] args) {
Child c = new Child();
c.setAge(10);
c.setName("张三");
System.out.println(c.getAge());
System.out.println(c.getName());
}
}
8.对象作为方法参数
public class Cat {
private String name;
private int age;
//alt + shift +s 选择Generate Constructor using Fields
public Cat(String name, int age) {
super();
this.name = name;
this.age = age;
}
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 class Day1111 {
public static void m1(Cat a) {
a.setAge(4);
}
public static void m2(Cat a) {
a = new Cat("c", 3);
}
public static void main(String[] args) {
Cat c1 = new Cat("a", 1);
System.out.println(c1.getAge()); //1
m1(c1);
System.out.println(c1.getAge()); //4
m2(c1);
System.out.println(c1.getAge()); //4
}
}
9.练习
1定义一个Person类(name,age,sno)进行数据封装,age的年龄范围设置为0到130,使用getAge返回年龄。
2,编写类Triangle,声明private的两个属性:底边长base和高height,同时提供getter和setter,在TriangleManager类中定义一个方法public static double getArea(Triangle t)计算三角形的面积,并在main方法中输出。