今天我们着重总结之前所学的所有知识点:
1.面向对象的三大特征:封装、继承、多态;2.了解final、权限、内部类;3.描述Scanner、Random、ArrayList的基本使用,最后完成一个不重复的点名程序;4.包装类的概念、装箱和拆箱、基本数据类型和字符串的相互转换。
一、面向对象三大特征
1.封装
封装是面向对象编程的核心思想,简单点说就是,我把某些东西封装起来,这些关键的核心的东西不能给你看,但是我可以提供给你一些简单使用的方法。
就说现在最最常用的手机,人人都会用,打电话、发短信、玩游戏、刷视频等等,但你知道手机怎么实现这些功能的吗??不知道吧,我们会用就可以了,怎么实现的对我们来说不重要。那这就很类似封装的理念了。
Java中类就是对具体事物的一种封装,类中的方法等等也是一种封装。我们把数据、一系列操作数据的函数封装到方法中,然后通过权限修饰符控制哪些方法可以让外知道,哪些只能自己知道,这样就能减少核心的数据被外界获取甚至破坏。
封装有三个好处:1.可以保护代码不被破坏,提高数据安全性。2.提高了代码的复用性(有些方法、类在很多地方都能多次反复使用)3.带来的高内聚和低耦合,使用不同对象、不同模块之间能更好的协同。
2.继承
类和类之间有些也会具有一定的关系,比方说四边形,可以分为正方形、长方形、菱形,他们不但继承了四边形的特征,也具有属于自己的特征,这就是一种继承的关系。
在Java继承可以使用 extends 关键字来实现,其中Java规定了java.lang.Object 类作为所有的类直接或间接的父类(当类没有继承其他类时,java默认继承Object类,当类继承了其他类时,可以向上追溯,最终继承的类就是Object类)。java规定类只能继承一个类。
子类不会继承父类的构造方法,但是会调用(子类初始化前会先初始化父类)。如果父类的构造器带有参数,则必须在子类的构造器中显式地通过 super 关键字调用父类的构造器并配以适当的参数列表(这就是Java要设置一个默认的无参构造的缘故)
关于继承,也有几个显著的特点:1.子类无法继承private修饰的属性和方法;2.子类和父类在同一包下,可以继承default权限的属性方法;3.子类可以对父类进行扩展,拥有自己的属性和方法;4.子类可以重写父类的方法(前提是可以继承到这个方法)
继承中的关键字:extends、super 、this、final
3.多态
多态指同一个实体同时具有多种形式。同字面意思,及一个对象在不同的情况下会有不同的体现。
3.1 类的多态
类的多态其实就是一种继承关系。
3.1.1 向上转型
向上转型其实就是父类对子类的引用。等边三角形是一种特殊的三角形,但是不管再怎么特殊它也是一个三角形。不管什么品种的狗我们都可以说它是一只动物。
这个特点其实就是设计原则中的里式替换原则的原理。子类至少是一个父类,所以父类出现的地方,其子类一定可以出现。
//狗继承与Animals ,所以可以向上转型,用Animals引用Dog类
//能引用是因为狗至少是一种动物,它有动物类所有属性和方法
Animals animals= new Dog();
3.1.2 向下转型
向下转型是讲父类转型位子类,这种转型通常会出现问题,在具体使用向下转型的时候需要使用显式类型转换。
向下转型通常配合 instanceof关键字使用,用于判断一个实例对象是否属于某个类,判断一个类是否实现了某个接口。
当我们使用向下转型时,可能会出现一些问题,所以在之前需要先判断一下。
class Animals {
public void sound(){
System.out.println("动物叫声");
}
}
class Dog extends Animals{
@Override
public void sound() {
System.out.println("狗叫声");
}
}
class main{
public static void main(String[] args) {
//向上转型
Animals a = new Dog();
a.sound();
//向下转型,先判断是否属于Dog的实例
if(a instanceof Dog){
Dog dog = (Dog)a;
dog.sound();
}
}
}
3.2 方法的多态
3.2.1 重写
重写父类的方法,名字、参数、返回值相同
public class Persion {
public void say(String name){
System.out.println("名字是:"+name);
}
}
public class Student extends Persion{
public void say(String name) { //重写了父类的方法,方法名和参数相同
System.out.println(name+"是一个学生");
}
}
3.2.2 重载
同一个类中的相同名字不同参数的方法
public void say(String name , String sex){}
public void say(String name,int age){ //重载方法,名字相同,但是传递参数的类型不同,系统能够判断,所以正确
}
public void say(String sex,String name){ //和第一个say具有相同类型的参数,所以系统无法判定,就会出现错误
}
二、了解final、权限、内部类
1. final关键字
final: 不可改变的。 可以用于修饰类、 方法和变量。
当它修饰类时: 被修饰的类, 不能被继承。
当它修饰方法时: 被修饰的方法, 不能被重写。
当它修饰变量时: 被修饰的变量, 不能被重新赋值。
基本类型的局部变量, 被final修饰后, 只能赋值一次, 不能再更改。
引用类型的局部变量, 被final修饰后, 只能指向一个对象, 地址不能再更改。 但是不影响对象内部的成员变量值的修改, 代码如下:
public class Demo {
public static void main(String[] args) {
// 创建 User 对象
final User u = new User();
// 创建 另一个 User对象
u = new User(); // 报错, 指向了新的对象, 地址值改变。
// 调用setName方法
u.setName("张三"); // 可以修改
}
}
2. 权限修饰符
在Java中提供了四种访问权限, 使用不同的访问权限修饰符修饰时, 被修饰的内容会有不同的访问权限
public: 公共的。
protected: 受保护的
default: 默认的
private: 私有的
不同权限的访问能力
public | protected | default(空的) | private | |
---|---|---|---|---|
同一类中 | √ | √ | √ | √ |
同一包中(子类与无关类) | √ | √ | √ | |
不同包的子类 | √ | √ | ||
不同包中的无关类 | √ |
注:不加权限修饰符, 其访问能力与default修饰符相同
3. 内部类
将一个类A定义在另一个类B里面, 里面的那个类A就称为内部类, B则称为外部类。
3.1 成员内部类
定义在类中方法外的类。如代码:
public class Person {
private boolean Study = true;
class Wen {
public void judge() {
// 直接访问外部类成员
if (Study) {
System.out.println("在学");
} else {
System.out.println("在玩");
}
}
}
public boolean isStudy() {
return Study;
}
public void setStudy(boolean Study) {
this.Study = Study;
}
}
访问特点:
内部类可以直接访问外部类的成员, 包括私有成员。
外部类要访问内部类的成员, 必须要建立内部类的对象。
定义测试类:
public class Demo {
public static void main(String[] args) {
// 创建外部类对象
Person p = new Person();
// 创建内部类对象
Person.Wen wen = p.new Wen();
// 调用内部类方法
wen.judge();
// 调用外部类方法
p.setStudy(false);
}
}
注:内部类仍然是一个独立的类, 在编译之后会内部类会被编译成独立的.class文件, 但是前面冠以外部类的类名和符号 。
3.2 匿名内部类
匿名内部类是内部类的简化写法。 它的本质是一个带具体实现的父类或者父接口的匿名的子类对象。
匿名内部类必须继承一个父类或者实现一个父接口。
以接口为例, 匿名内部类的使用, 代码如下:
// 定义接口
public interface Fly {
public abstract void fly();
}
// 创建匿名内部类, 并调用
public class Demo {
public static void main(String[] args) {
/*
1. 等号右边: 是匿名内部类, 定义并创建该接口的子类对象
2. 等号左边: 是多态赋值, 接口类型引用指向子类对象
*/
Fly f = new Fly() {
public void fly() {
System.out.println("我飞了~~~");
}
};
//调用 fly方法, 执行重写后的方法
f.fly();
}
}
通常在方法的形式参数是接口或者抽象类时, 也可以将匿名内部类作为参数传递。 代码如下:
public class Demo {
public static void main(String[] args) {
/*
创建匿名内部类, 直接传递给showFly(FlyAble f)
*/
showFly(new Fly() {
public void fly() {
System.out.println("我飞了~~~");
}
});
}
public static void showFly(Fly f) {
f.fly();
}
}
三、描述Scanner、Random、ArrayList的基本使用,最后完成一个不重复的点名程序
1. Scanner类
Scanner类是一个可以解析基本类型和字符串的简单文本扫描器。
使用步骤:
-
导包
使用import关键字导包, 在类的所有代码之前导包, 引入要使用的类型, java.lang包下的所有类无需导入。
-
创建对象
使用该类的构造方法, 创建一个该类的对象。
-
调用方法
调用该类的成员方法, 完成指定功能。
使用Scanner类, 完成接收键盘录入数据的操作, 代码如下:
//1. 导包
import java.util.Scanner;
public class Demo01_Scanner {
public static void main(String[] args) {
//2. 创建键盘录入数据的对象
Scanner sc = new Scanner(System.in);
//3. 接收数据
System.out.println("请录入一个整数: ");
int i = sc.nextInt();
//4. 输出数据
System.out.println("i: " + i);
}
}
2. Random类
此类的实例用于生成伪随机数。
使用Random类, 完成生成3个1 0以内的随机整数的操作, 代码如下:
import java.util.Random;
public class Demo {
public static void main(String[] args) {
//2. 创建键盘录入数据的对象
Random r = new Random();
for (int i = 0; i < 3; i++) {
//3. 随机生成一个数据
int number = r.nextInt(10);
//4. 输出数据
System.out.println("number: " + number);
}
}
}
3.ArrayList类
ArrayList 是大小可变的数组的实现, 存储在内的数据称为元素。 此类提供一些方法来操作内部存储的元素。 ArrayList 中可不断添加元素, 其大小也自动增长。
java.util.ArrayList :
, 表示一种指定的数据类型, 叫做泛型。 E , 取自Element(元素) 的首字母。 在出现 E 的地方, 我们使用一种引用数据类型将其替换即可, 表示我们将存储哪种引用类型的元素。
使用ArrayList类, 存储三个字符串元素, 代码如下:
import java.util.ArrayList;
public class Demo {
public static void main(String[] args) {
//创建学生数组
ArrayList<String> list = new ArrayList<>();
//创建学生对象
String s1 = "张三";
String s2 = "李四";
String s3 = "王五";
//打印学生ArrayList集合
System.out.println(list);
//把学生对象作为元素添加到集合
list.add(s1);
list.add(s2);
list.add(s3);
//打印学生ArrayList集合
System.out.println(list);
}
}
4.完成一个不重复的点名程序
package dm;
import java.util.*;
public class chou {
public static void main(String[] args) {
List<String> list = Arrays.asList("张三","王五","沈六","陈十","赵四");
ArrayList<String> name=new ArrayList<>(list);
Random random=new Random();
Scanner scanner=new Scanner(System.in);
while (true){
System.out.println("请输入A/a开始点名");
String a=scanner.next();
if (a.equals("A")||a.equals("a")){
int indeax = random.nextInt(name.size());
String string=name.get(indeax);
System.out.println(string);
name.remove(indeax);
if (name.size()==0){
System.out.println("点名结束");
break;
}
}else {
System.out.println("点名结束");
break;
}
}
}
}
四、包装类的概念、装箱和拆箱、基本数据类型和字符串的相互转换
1.包装类的概念:
通常情况下基本数据类型的变量不是对象,为了满足万物皆对象的理念就 需要对基本数据类型的变. 量进行打包封装处理变成对象,而负责将这些变量声明为成员变量进行对象化处理的相关类,叫做包装类。
2.装箱和拆箱
装箱:把基本数据类型转换成包装类型 拆箱:把包装类型转换成基本数据类型
2.1 数据装箱:
将基本数据类型保存到包装类之中,一般利用构造方法完成
Integer类 : public Integer(int value);
Double类 : public Double(double value);
Boolean : public Boolean(boolean value);
2.2 数据拆箱:
从包装类中获取基本数据类型
数值型包装类已经由 Number 类定义了拆箱的方法;
Boolean型:public boolean booleanValue();
2.3 自动装箱和自动拆箱
int a1=5;
Integer a2 = 5;
System.out.println(a1);
System.out.println(a2);
System.out.println("--------------------");
//装箱:把基本数据类型转换成包装类型
//拆箱:把包装类型转换成基本数据类型
//装箱
Integer a3= new Integer(a1);
Integer a4= Integer.valueOf(a1);
//拆箱
int a5 =a3.intValue();//把a3通过调用方法后换成int类型
System.out.println("--------------------");
//自动装箱和自动拆箱
//自动装箱
Integer a6= a1;
//自动拆箱
int a7=a3;
System.out.println("--------------------");
3. 基本数据类型和字符串的相互转换
八种基本数据类型
整数类型:byte、short、int、long
小数类型:float、double
字符类型:char
布尔类型:boolean
3.1 基本类型转换为字符串
有三种方法:
-
使用包装类的 toString() 方法
-
使用String类的 valueOf() 方法
-
用一个空字符串加上基本类型,得到的就是基本类型数据对应的字符串
//将基本类型转换为字符串(其他基本类型同理)
int a = 16;
String s1 = Integer.toString(a); //方法1
String s2 = String.valueOf(a); //方法2
String s3 = a + ""; //方法3
3.2 将字符串转换成基本类型
有两种方法:
-
调用包装类的 parseXxx 静态方法。
-
调用包装类的 valueOf() 方法转换为基本类型的包装类,会自动拆箱
//将字符串转换为基本类型
String s = "16";
int a = Integer.parseInt(s); //方法1
int b = Integer.valueof(s); //方法2