本节内容为昨天未讲完的内容
本节知识大纲:
构造器
构造器
在类中用来创建对象的那个方法称之为构造器或者构造函数或者构造方法
1:构造器是一个特殊的方法:
a:方法名称和类名相同
b:方法无返回值
c:在方法中无须显示的return返回数据
d:构造器是允许方法重载的
e:所有类默认情况下都会存在一个无参构造器,如果在当前类中显式的声明了构造器之后,无参构造器就 不存在了
2:构造器的作用就是用来创建对象的
构造器的调用只能通过new关键词去调用
当给一个类中的成员变量类型声明为基本数据类型之后,导致基本数据类型存在默认值。
未赋值的情况下存在值,后续的逻辑可能存在问题。
public class Student {
static int count = 1;
int id;
String name;
int gender;// 0 代表男 1代表女
String clz;
public Student() {
this("张三");
System.out.println("我被调用了。。。。");
//study();
}
public Student(String name) {
this.name = name;
}
public Student(String name,int gender) {
this(name,gender,count++,"0708");
}
public Student(String name,int gender,int id,String clz) {
this.name = name;
this.gender = gender;
this.id = id;
this.clz = clz;
}
public void study() {
System.out.println(this.name+"day day up");
System.out.println(this.info());
}
public String info() {
return "Student[id:"+this.id+",name:"+this.name+""+ ",gender:"+(this.gender==0?"男":"女")+",clz:"+this.clz+"]";
}
}
this的用法
this的用法:
this.
当前对象的-》 谁在调用 代表谁
可省略:
不可省略:
区分同名变量,局部变量和成员变量
this()
构造器之间的互相调用
this():一定要在构造器的首行
public class Student {
static int count = 1;
int id;
String name;
int gender;// 0 代表男 1代表女
String clz;
public Student() {
this("张三");
System.out.println("我被调用了。。。。");
//study();
}
public Student(String name) {
this.name = name;
}
public Student(String name,int gender) {
this(name,gender,count++,"0708");
}
public Student(String name,int gender,int id,String clz) {
this.name = name;
this.gender = gender;
this.id = id;
this.clz = clz;
}
public void study() {
System.out.println(this.name+"day day up");
System.out.println(this.info());
}
public String info() {
return "Student[id:"+this.id+",name:"+this.name+""
+ ",gender:"+(this.gender==0?"男":"女")+",clz:"+this.clz+"]";
}
}
public class Test01 {
public static void main(String[] args) {
//创建一个Student对象 通过带参构造器
/*
* Student stu = new Student("lisi");
*
* stu.study();
*
*
* Student stu1 = new Student("王二麻子"); stu1.study();
*/
Student s1 = new Student("张三",0);
System.out.println(s1.info());
Student s2 = new Student("lisi",0);
System.out.println(s2.info());
}
}
引用类型讲过方法
基本数据类型经过方法之后 其值不变。值传递
引用数据类型进过方法之后 其值会变,值传递(地址值)
通过两个变量指向了同一个内存地址,一个对内存进行改变 另一个可见
public class Test02 {
public static void main(String[] args) {
int num = 10;
change(num);
System.out.println("main:"+num);
//声明一个dog对象
Dog d = new Dog();
d.color = "白色";
d.name = "张二狗";
System.out.println(d.info());
change(d);
System.out.println("main:"+d.info());
}
public static void change(int num) {
num++;
System.out.println("change:"+num);
}
public static void change(Dog dog) {
dog.name = "旺财";
dog.color = "屎黄色";
System.out.println("change:"+dog.info());
}
}
class Dog{
String name;
String color;
public Dog() {
}
public void run() {
System.out.println("run。。。。。");
}
public String info() {
return "name:"+this.name+",color"+this.color;
}
}
继承
继承的优势:
在一定程度上提高了代码的复用性
继承编写:
子类 extends 父类 子类拥有父类中的所有的属性以及方法
什么是继承: 子承父业,
将多个类中的共性再一次抽取,可以抽取为一个父类。父类的作用就是用来将一些重复的内容不再多次编写(提高代码复用性)
注意事项:
java中只支持单继承 一个子类有且只能有一个父类 复用性的提高是有限的
多继承好还是单继承好
多继承 :极大提高代码复用性 但是代码调用的复杂度也提升了
单继承:代码调用的复杂度比较低,但是复用性比较有限
假设在应用场景中:
A->B 后期随着业务不断扩展,导致A需要继承C时一般的解决办法:A->B->C,但是该种解决办法随着后期业务的不断升级,导致整个继承连会变得极其复杂,既不利于后期维护以及拓展。
所以能不能用继承就别用继承。
public class Person {
String name;
int age;
int gender;
public Person() {
}
public void eat() {
System.out.println(this.name+"在吃饭");
}
/*
* public void run(Car c) {
*
* }
*/
}
public class Student extends Person{
int id;
public Student() {
}
public void study() {
System.out.println(this.name+"在学习");
}
}
public class Teacher extends Person{
double sal;
public Teacher() {
}
public void working() {
System.out.println(this.name+"在工作");
}
}
public class Test {
public static void main(String[] args) {
//创建一个学生对象
Student stu = new Student();
stu.name = "小鱼鱼";
stu.eat();
stu.study();
//创建一个老师对象
Teacher t = new Teacher();
t.name = "老薛";
t.sal = 1000000000;
t.eat();
t.working();
}
}
当创建子类对象时 会先执行父类的构造器
super: 和this的用法一模一样
super.
当前对象的父类对象的
super. 可省略的:
super和this的用法是重复的 都可以省略
super. 不可省略
如果子类和父类中出现了同名变量或者是同名方法
super()
调用父类的构造器,默认情况下调用的父类的无参构造器(默认情况下每个类中都存再一个无参构造器 哪怕不写
也存在)
当父类中存在其他构造器时,无参构造器不存在,此时如果再子类中没有通过super()显示的指定调用的构造器
会导致程序报错。
在构造器中this()和super()不能同时出现,如果两个都不存在,默认是存在的super()。
public class Test01 {
public static void main(String[] args) {
// 创建一个子类对象
Dog d = new Dog();
//d.lookDoor();
}
}
class Animal{
String name;
public Animal() { System.out.println(" Animal 我被调用了......."); }
public Animal(String name) {
this.name = name;
System.out.println(" Animal 带参构造器 我被调用了.......");
}
public void eat() {
System.out.println("animal 吃东西");
}
}
class Dog extends Animal{
String nickName;
public Dog() {
this("呵呵");
System.out.println(" DOG 我被调用了。。。");
}
public Dog(String nickName) {
//super("hehe");
this.nickName = nickName;
System.out.println("DOG 才参数的");
}
public void lookDoor() {
System.out.println("看门");
super.eat();
}
public void eat() {
System.out.println("dog 吃东西");
}
}
方法重写
在子类中定义了和父类中同名的方法 我们将该方法称之为重写方法(覆盖)
为什么需要重写?
父类的功能不能满足子类的需求。子类在父类的基础上进行了扩展。
如何确定一个方法是重写方法?
在子类的方法上加入@Overried 注解 如果不报错 证明是重写
重写的前提:
一定要发生继承关系。并且子类的方法名和父类的方法名同名
参数列表要一样
返回类型要一样
public class Test03 {
public static void main(String[] args) {
//创建一个子类对象
S s = new S();
s.study();
s.marry();
s.work();
}
}
/**
* 爱情观
*
* @author wawjy
*
*/
class F{
String name;
public F() {
}
public int study() {
System.out.println("好好学习 时间观念及其严苛");
return 1;
}
public void marry() {
System.out.println("赶紧结婚 我要抱孙子");
}
public void work() {
System.out.println("赶紧去挣奶粉钱。。。。。");
}
}
class S extends F{
public S() {
}
@Override
public int study() {
System.out.println("开心很重要 开心的学习");
return 1;
}
}
object
Object: 是所有类的根基类 超类 父类
当一个类没有显式的继承关系的时候,默认情况下他的父类都是Object
Object:
ctrl+O 罗列当前类中的所有方法
finalize: gc回收垃圾时 自动调用finalize
wait
notify
notifyAll
--- 学习多线程时候会讲
clone: 克隆 (创建对象的一种方式 深浅复制)
hashCode: 哈希码 -> 哈希算法 唯一的值
getClass:获取当前类的Class对象 反射
输出一个对象的时候默认情况下会调用当前对象的toString
== 比较基本数据类型比较的是值 比较引用类型比较的是地址
equals:用来比较相等的 如果相等返回true 反之返回false
Object中的比较是通过==比较的
public class Test04 {
public static void main(String[] args) {
//创建一个Test04 对象
Test04 t = new Test04();
//创建一个Bird对象
Bird b = new Bird();
System.out.println(b);
System.out.println(b.toString());
// 创建一个bird对象
Bird b1 = new Bird();
// 比较相等的
boolean flag = b.equals(b1);
System.out.println(flag);
}
}
class Bird{
String color;
String type;
public Bird() {
}
@Override
public String toString() {
return "Bird{color:"+this.color+",type:"+this.type+"}";
}
}
封装
public 修饰的人见人爱型 都能访问 被public修饰的方法、类、变量能被所有类可见
protected 同包下可见 异包下子类可见
默认的: 不写 远亲不如近邻 同包下可见 异包下不可见
private: 自私自利 本类可见
本类 同包下子类 同包下无关类 异包子类 异包下无关类
public √ √ √ √ √
protected √ √ √ √ ×
默认的 √ √ √ × ×
private √ × × × ×
public class Test01 {
public static void main(String[] args) {
// 创建一个Student
Student stu = new Student();
//stu.age = 100;
//System.out.println("stu的年龄是:"+stu.age);
stu.setGender(3);
System.out.println("stu的年龄是:"+stu.getGender());
}
}
class Student{
private int gender;
private int age;
public Student() {
}
public int getGender() {
return gender;
}
public void setGender(int gender) {
this.gender = gender;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
class ArrayList{
private int size;// 实际存储容量
private int capacity;// 实际数组容量
public int getSize() {
return size;
}
public void setSize(int size) {
this.size = size;
}
}
修饰方法
修饰符的作用是用来屏蔽一些底层的实现逻辑,降低调用者(程序员)的复杂度。
确保当前类更加安全。
修饰符可以修饰 类
属性(成员变量) :
避免随意.属性,修改获取属性 造成数据不安全
如果用private修饰的话 一定要保证对外提供get、set方法让外部可见
方法:
屏蔽底层调用细节,降低调用者(程序员)的复杂度 使得代码更加健壮
public private
public class FlowerUtil {
public static boolean isFlower(int num) {
//获取累加的和
int sum = sum(num);
return num==sum;
}
private static int sum(int num) {
//声明存放累加的结果
int result = 0;
// 声明一个方法 计算一个数字的长度 位数
int length = length(num);
while(num!=0) {
//分离每一位
int bit = num%10;
result = result+pow(bit,length);
num = num/10;
}
return result;
}
public static int pow(int bit,int length) {
int result = 1;
for(int i = 1;i<=length;i++) {
result = result*bit;
}
return result;
}
public static int length(int num) {
int length = 0;
while(num!=0) {
num = num/10;
length++;
}
return length;
}
}