基础知识
2.类
就是将我们具体的事物抽象出来
静态属性抽象成类的成员变量
动态属性抽象成类的成员方法
1 class Person {
2 private String name;
3 private int age;
4 ...说话,吃饭等成员方法
5 }
3.成员变量和局部变量的区别
* A:在类中的位置不同
* 成员变量:在类中方法外
* 局部变量:在方法定义中或者方法声明上
* B:在内存中的位置不同
* 成员变量:在堆内存(成员变量属于对象,对象进堆内存)
* 局部变量:在栈内存(局部变量属于方法,方法进栈内存)
* C:生命周期不同
* 成员变量:随着对象的创建而存在,随着对象的消失而消失
* 局部变量:随着方法的调用而存在,随着方法的调用完毕而消失
* D:初始化值不同
* 成员变量:有默认初始化值
* 局部变量:没有默认初始化值,必须定义,赋值,然后才能使用
注意事项:
* 局部变量名称可以和成员变量名称一样,在方法中使用的时候,采用的是就近原则
1 String name;//成员变量
2 int num;//成员变量
3 public void speak() {
4 int num = 10;//局部变量
5 System.out.println(name);
6 System.out.println(num);
7 }
结果:
null
10
4.匿名对象
* A:什么是匿名对象
* 没有名字的对象
* B:匿名对象应用场景
* a:调用方法,仅仅只调用一次的时候。
* 那么,这种匿名调用有什么好处吗?
* 节省代码
* 注意:调用多次的时候,不适合。
匿名对象调用完毕就是垃圾,可以被垃圾回收器回收。
匿名对象只适合对方法的一次调用,因为调用多次就会产生多个对象,不如用有名字的对象
下面的代码毫无意义:
new Car().color = "red";
new Car().num = 8;
new Car().run();
5.封装
* A:封装概述
* 是指隐藏对象的属性和实现细节,仅对外提供公共访问方式
* B:封装好处
* 隐藏实现细节,提供公共的访问方式
* 提高了代码的复用性
* 提高安全性
* C:封装原则
* 将不需要对外提供的内容都隐藏起来
* 把属性隐藏,提供公共方法对其访问
封装在代码中无处不在,代码中每一个entity类都是封装来的
6.关键字private
private关键字特点
* a:是一个权限修饰符
* b:可以修饰成员变量和成员方法
* c:被其修饰的成员只能在本类中被访问
案例演示
* 封装和private的应用:
* A:把成员变量用private修饰
* B:提供对应的getXxx()和setXxx()方法
1 class Person {
2 String name;
3 private int age;
4 set,get方法
5 }
6 class Demo1_Person {
7 public static void main(String[] args) {
8 Person p1 = new Person();
9 p1.name = "张三";//这样是可以赋值的
10 p1.age = -17;//不能赋值,因为age属性是私有的,不能在其它类中被访问,这里只能调用set方法赋值
11 }
12 }
//注:私有化的成员变量,是可以在本类中直接使用的,如上name,也可以写this.name,this可以省略...
7.关键字this
* A:this关键字特点
* 代表当前对象的引用
this代表其所在函数所属对象的引用,哪个对象调用了this所在的函数,this就代表这个对象
* B:案例演示
* this的应用场景
* 用来区分成员变量和局部变量重名
案例:
1 class Person {
2 private String name;
3 private int age;
4 public void setAge(int age) {//设置年龄
5 if (age > 0 && age < 200) {
6 this.age = age;//哪个对象来调用setAge()方法,this就代表哪个对象
7 }
8 }
9 }
8.构造方法
给对象的数据(属性)进行初始化
* B:构造方法格式特点
* a:方法名与类名相同
* b:没有返回值类型,连void都没有
* c:没有具体的返回值return;
1 private String name;
2 private int age;
3 public Stu() {
4 super();
5 }
6 public Stu(String name, int age) {
7 super();
8 this.name = name;
9 this.age = age;
10 }
9.重载
定义:方法名相同,参数列表不一样的方法
无参构造有参构造就是重载
10.关键字static
意为静态
* A:static关键字的特点
* a:随着类的加载而加载
* b:优先于对象存在:随着字节码文件的加载而加载的,那时候还没有对象呢!
* c:被类的所有对象共享
* 举例:咱们班级的学生应该共用同一个班级编号。
* 其实这个特点也是在告诉我们什么时候使用静态?
* 如果某个成员变量是被所有对象共享的,那么它就应该定义为静态的
* 举例:
* 饮水机(用静态修饰)
* 水杯(不能用静态修饰)
* 共性用静态,特性用非静态
* d:可以通过类名调用
* 其实它本身也可以通过对象名调用
* 推荐使用类名调用,在工具类中常用
* 静态修饰的内容一般我们称其为:与类相关的,类成员(静态变量:类变量,静态方法:类方法)
面试题:
在静态方法中可以出现this这个关键字吗?
显然是不能的,this指的是一个具体的对象,而静态在加载到内存时还没有具体的对象,静态是随着类的加载而加载的,静态比对象优先存在
静态方法只能访问静态的成员变量和静态的成员方法
怎样理解:
1 class Demo {
2 int num1 = 10;
3 static int num2 = 20;
4 public static void print1() {
5 System.out.println(num1);
6 //该方法与变量num2都是静态的,类创建后它们就创建了,然而这时还没有变量num1(该变量是成员变量,当对象创建的时候才会产生),怎么访问,所以在静态中只能访问静态
7 System.out.println(num2);
8 }
9 }
静态变量和成员变量的区别:
* 静态变量也叫类变量,成员变量也叫对象变量
* A:所属不同
* 静态变量属于类,所以也称为为类变量
* 成员变量属于对象,所以也称为实例变量(对象变量)
* B:内存中位置不同
* 静态变量存储于方法区的静态区
* 成员变量存储于堆内存
* C:内存出现时间不同
* 静态变量随着类的加载而加载,随着类的消失而消失
* 成员变量随着对象的创建而存在,随着对象的消失而消失
* D:调用不同
* 静态变量可以通过类名调用,也可以通过对象调用
* 成员变量只能通过对象名调用
面向对象02:
1.代码块
* A:代码块概述
* 在Java中,使用{}括起来的代码被称为代码块。
* B:代码块分类
* 根据其位置和声明的不同,可以分为局部代码块,构造代码块,静态代码块,同步代码块
* C:常见代码块的应用
* a:局部代码块(只要是和局部有关系的,都是和方法有关系的)
* 在方法中出现;限定变量生命周期,及早释放,提高内存利用率
* b:构造代码块 (初始化块)
* 在类中方法外出现;多个构造方法方法中相同的代码存放到一起,每次调用构造都执行,并且在构造方法前执行
* c:静态代码块
* 在类中方法外出现,并加上static修饰;用于给类进行初始化,在加载的时候就执行,并且只执行一次
* 一般用于加载驱动
所以有什么方法是要在类加载后就执行的(而且只需要执行一次)可以写成静态代码块
有时有些常量Map,List写法也可以用static,只需要在类存在的时候就给成员变量(这里是常量)赋值就可以了
这里使用static
如下:
public class PersonVo {
private int age;
private String name;
private String sex;
public static final Map<String, String> fenleiMap;
static {
System.out.println("----------static fenleiMap-----------");
Map<String, String> temp = new HashMap<>();
temp.put("A", "好人");
temp.put("B", "坏人");
fenleiMap = Collections.unmodifiableMap(temp);
}
}
案例:
1 public class Mxdx { 2 //构造块,每次执行构造方法,都会执行它,就是说每次创建新对象都会先执行这个 3 { 4 System.out.println("gou zhao kuai"); 5 } 6 //类加载的时候就执行,只执行一次,一般用于加载驱动:如数据库连接 7 static { 8 System.out.println("jin tai kuai"); 9 } 10 11 private String name; 12 private int age; 13 public Mxdx() { 14 super(); 15 // TODO Auto-generated constructor stub 16 System.out.println("kon can"); 17 } 18 public Mxdx(String name, int age) { 19 super(); 20 this.name = name; 21 this.age = age; 22 System.out.println("you can"); 23 }
...set,get方法 36 }
1 public class MxdxTest { 2 public static void main(String[] args) { 3 Mxdx m1 = new Mxdx(); 4 m1.setName("张三"); 5 6 Mxdx m2 = new Mxdx(); 7 m2.setName("李四"); 8 9 Mxdx m3 = new Mxdx("王五", 11); 10 } 11 }
运行结果:
jin tai kuai
gou zhao kuai
kon can
gou zhao kuai
kon can
gou zhao kuai
you can
2.继承
让类与类之间产生关系,子父类关系
目的:子类继承父类的变量和方法
继承的好处和弊端:
* A:继承的好处
* a:提高了代码的复用性,父类就是被复用的
* b:提高了代码的维护性
* c:让类与类之间产生了关系,是多态的前提
* B:继承的弊端
* 类的耦合性增强了。类与类之间的关系太紧密,一边添加属性,另一边就多了一个,有的时候是期望的,但是有的时候是不期望的
* 开发的原则:高内聚,低耦合。就是指自己完成事情的能力,自己能完成就不要麻烦别人
* 耦合:类与类的关系
Java中类的继承特点:
* A:Java中类的继承特点
* a:Java只支持单继承,不支持多继承。(一个儿子只能有一个爹,多继承是有安全隐患的,如A继承B,C,因为BC中属性可能是矛盾的,这样继承会有问题,所以不能多继承)
* b:Java支持多层继承(继承体系),如A继承B继承C,田园犬继承犬继承动物
继承的注意事项和什么时候使用:
* A:继承的注意事项
* a:子类只能继承父类所有非私有的成员(成员方法和成员变量)
* b:子类不能继承父类的构造方法,但是可以通过super关键字去访问父类构造方法。
* c:不要为了部分功能而去继承
* 项目经理 姓名 工号 工资 奖金
* 程序员 姓名 工号 工资
* B:什么时候使用继承
* 继承其实体现的是一种关系:"is a"。
Person
Student
Teacher
水果
苹果
香蕉
橘子
采用假设法。
如果有两个类A,B。只有他们符合A是B的一种,或者B是A的一种,就可以考虑使用继承。
案例:
1 class Demo3_Extends { 2 public static void main(String[] args) { 3 Son s = new Son(); 4 s.show(); 5 } 6 } 7 class Father { 8 private String name; 9 private void show() { 10 System.out.println("Hello World!"); 11 } 12 } 13 14 class Son extends Father { 15 }
面向对象03:
1.多态
所谓多态就是事物存在的多种形态
表现形式是父类引用指向子类对象
多态前提:
* a:要有继承关系
* b:要有方法重写
* c:要有父类引用指向子类对象
重写:
就是子类中写了和父类相同的方法,将父类方法覆盖
这样子类在调用该方法时,就直接调用自己的方法,而不是父类的方法
案例:
1 class Demo1_Polymorphic {
2 public static void main(String[] args) {
3 Cat c = new Cat();
4 c.eat();
5
6 Animal a = new Cat();
7 //创建一个动物,这个动物是只猫,这没问题,父类引用指向子类对象
8 a.eat();//这里结果是猫吃鱼
9 }
10 }
11 class Animal {
12 public void eat() {
13 System.out.println("动物吃饭");
14 }
15 }
16
17 class Cat extends Animal {
18 public void eat() {
19 System.out.println("猫吃鱼");
20 }
21 }
看看下面的例子:
1 class SuperMan extends Person {
2 String name = "superMan";
3
4 public void talkTrade() {
5 System.out.println("谈几个亿的大单子");
6 }
7
8 public void fly() {
9 System.out.println("飞出去救人");
10 }
11 }
1 public class Person {
2 String name = "John";
3 public void talkTrade() {
4 System.out.println("谈生意");
5 }
6 }
1 public class Demo3_SuperMan {
2 public static void main(String[] args) {
3 Person p = new SuperMan();//向上转型
4 System.out.println(p.name);//没有用到多态,调用的是父类的属性
5 p.talkTrade();//只有这里用到了多态,因为只有这里运用的是重写的方法
6 //p.fly(),能这样写吗?是不能的,因为超人被提升为人了,而父类是不能调用子类方法的,这里p是父类对象,只有当满足多态条件时,才会看成子类对象
7 SuperMan sm = (SuperMan)p;//向下转型
8 sm.fly();
9 }
10 }
运行结果:
John
谈几个亿的大单子
飞出去救人
为什么会出现这个结果,注释中解释了
2.多态中向上转型和向下转型
1 public static void method(Animal a) {
2 //当作参数的时候用多态最好,因为扩展性强
3 //当传入对象是猫或者狗的时候,实际上Animal a = 猫,所以用到多态了
4 //关键字 instanceof 判断前边的引用是否是后边的数据类型
5 if (a instanceof Cat) {
6 Cat c = (Cat)a;
7 c.eat();
8 c.catchMouse();
9 }else if (a instanceof Dog) {
10 Dog d = (Dog)a;
11 d.eat();
12 d.lookHome();
13 }else {
14 a.eat();
15 }
16 }
4.关键字abstract
意为抽象,就是看不懂,你不知道
* a:抽象类和抽象方法必须用abstract关键字修饰
* abstract class 类名 {}
* public abstract void eat();//不知道该方法具体是怎么实现的
//比如动物吃,你知道它吃什么吗?怎么吃?都不知道
* b:抽象类不一定有抽象方法,有抽象方法的类一定是抽象类或者是接口
* c:抽象类不能实例化那么,抽象类如何实例化呢?
* 按照多态的方式,由具体的子类实例化。其实这也是多态的一种,抽象类多态
* d:抽象类的子类
* 要么是抽象类
* 要么重写抽象类中的所有抽象方法
1 abstract class Animal { //抽象类
2 public abstract void eat(); //抽象方法,子类继承抽象类,抽象方法是强制要重写的,和接口一样,不重写,抽象还有什么意义
3 public Animal() {
4 System.out.println("父类空参构造");
5 }
6 }
7 class Cat extends Animal {
8 public Cat() {
9 super();
10 }
11
12 @Override
13 public void eat() {
14 // TODO Auto-generated method stub
15 System.out.println("mao ci yu");
16 }
17 }
18 class Demo1_Abstract {
19 public static void main(String[] args) {
20 //Animal a = new Animal(); //错误: Animal是抽象的; 无法实例化
21 Animal a = new Cat(); //父类引用指向子类对象
22 a.eat();
23 }
24 }
//可以把抽象类看作是接口,都是无法实例化的,都是子类必须重写方法的....
运行结果:
父类空参构造
mao ci yu
抽象类的成员特点:
* A:抽象类的成员特点
* a:成员变量:既可以是变量,也可以是常量。abstract是否可以修饰成员变量?不能修饰成员变量
* b:构造方法:有
* 用于子类访问父类数据的初始化
* c:成员方法:既可以是抽象的,也可以是非抽象的
* B:案例演示
* 抽象类的成员特点
* C:抽象类的成员方法特性:
* a:抽象方法,强制要求子类做的事情。
* b:非抽象方法,子类继承的事情,提高代码复用性
1 abstract class Demo {
2 int num1 = 10;//变量
3 final int num2 = 20;//常量
4
5 public Demo(){}//构造方法
6
7 public void print() {//非抽象方法,子类可以直接使用
8 System.out.println("我是码农");
9 }
10
11 public abstract void method();//抽象方法,子类必须实现
12 }
13
14 class Test extends Demo {
15 public void method() {
16 System.out.println("绝地求生");
17 }
18 }
* A:面试题1
* 一个抽象类如果没有抽象方法,可不可以定义为抽象类?如果可以,有什么意义?
* 可以
* 这么做目的只有一个,就是不让其他类创建本类对象,交给子类完成
* B:面试题2
* abstract不能和哪些关键字共存
不能与static,final,final共存
abstract和static
被abstract修饰的方法没有方法体
被static修饰的可以用类名.调用,但是类名.调用没有实现的抽象方法有什么意义
abstract和final
被abstract修饰的方法强制子类重写
被final修饰的不让子类重写,所以他俩是矛盾
abstract和private
被abstract修饰的是为了让子类看到并强制重写
被private修饰不让子类访问,子类都不能访问了,还重写个啥啊
5.接口:
* A:接口概述
* 从狭义的角度讲就是指java中的interface
* 从广义的角度讲对外提供规则的都是接口
* B:接口特点
* a:接口用关键字interface表示
* interface 接口名 {}
* b:类实现接口用implements表示
* class 类名 implements 接口名 {}
* c:接口不能实例化
* 那么,接口如何实例化呢?
* 按照多态的方式来实例化
* d:接口的子类
* a:可以是抽象类。但是意义不大
* b:可以是具体类。要重写接口中的所有抽象方法,代码中无处不在
* A:接口成员特点
* 成员变量只能是常量,并且是静态的并公共的
* 默认修饰符:public static final
* 构造方法:接口没有构造方法
* 成员方法:只能是抽象方法
* 默认修饰符:public abstract
1 public interface Inter {
2 public static final int num = 10;//这里写不写public static final都会默认加上
3 public abstract void print();//这里写不写public abstract都会默认加上,因为写接口本来就是为了实现的啊,会默认加上abstract
4 }
1 class Demo implements Inter {
2 public Demo() {
3 super();
4 }
5 public void print() {
6 //num = 20;num已经被final修饰了,不能重新赋值
7 System.out.println(num);
8 }
9 }
1 public class Demo2_Interface {
2 public static void main(String[] args) {
3 Demo d = new Demo();
4 d.print();
5 System.out.println(Inter.num);
6 }
7 }
运行结果:
10
10
类与类,类与接口的关系:
* a:类与类:
* 继承关系,只能单继承,可以多层继承
* b:类与接口:
* 实现关系,可以单实现,也可以多实现
* 并且还可以在继承一个类的同时实现多个接口
抽象类和接口的区别:
两者都会用到关键字abstract ,有什么区别呢
* A:成员区别
* 抽象类:
* 成员变量:可以变量,也可以常量
* 构造方法:有
* 成员方法:可以抽象,也可以非抽象
* 接口:
* 成员变量:只可以常量
* 成员方法:只可以抽象
在接口中变量和方法都作了限制
设计理念上的区别
* 抽象类 被继承体现的是:”is a”的关系。抽象类中定义的是该继承体系的共性功能,是为了给子类根据自身需要,重写重写抽象方法,所以抽象类是共性功能的提取
* 接口 被实现体现的是:”like a”的关系。接口中定义的是该继承体系的扩展功能,也就是说要扩展的时候常写一个接口,如果想要该功能就去实现这个接口
* 对事物本质的抽象用抽象类,对事物功能的扩展用接口
看看下面代码就明白了:
1 abstract class Animal {
2 private String name;
3 private int age;
4 public Animal() {}
5 public Animal(String name,int age) {
6 this.name = name;
7 this.age = age;
8 }
9
10 public void setName(String name) {
11 this.name = name;
12 }
13
14 public String getName() {
15 return name;
16 }
17
18 public void setAge(int age) {
19 this.age = age;
20 }
21
22 public int getAge() {
23 return age;
24 }
25 public abstract void eat();
26 public abstract void sleep();
27 }
1 class Cat extends Animal {
2 public Cat() {}
3 public Cat(String name,int age) {
4 super(name,age);
5 }
6 public void eat() {
7 System.out.println("猫吃鱼");
8 }
9 public void sleep() {
10 System.out.println("侧着睡");
11 }
12 }
1 interface Jumping {
2 public void jump();
3 }
1 class JumpCat extends Cat implements Jumping {
2 public JumpCat() {}
3 public JumpCat(String name,int age) {
4 super(name,age);
5 }
6 public void jump() {
7 System.out.println("猫跳高");
8 }
9 }
1 public class Test1_Animal {
2 public static void main(String[] args) {
3 Cat c = new Cat("加菲",8);
4 c.eat();
5 c.sleep();
6 JumpCat jc = new JumpCat("跳高猫",3);
7 jc.eat();
8 jc.sleep();
9 jc.jump();
10 }
11 }
运行结果:
猫吃鱼
侧着睡
猫吃鱼
侧着睡
猫跳高
现在看看这些面向对象中的设计,都是有道理的,都是观察现实中的事物,然后抽取出来的
为实现不同的功能而设计的
Java语言,不管是什么编程语言,这些设计者是真的厉害