视频地址:http://www.51zxw.net/study.asp?vip=5570608
本节内容是根据51自学网的壁虎老师讲解的java视频教学做的笔记,0基础的看51自学网壁虎老师的视频是最恰当不过的,我看了三四年了,反反复复的看好几遍(其实每次看都木有看完,看了前几章就不看了,过了好久好久又想用java还去看一遍,每次又木有看完,没有把基础全看完,所以java一直学不会,这次咬牙坚持把最后一章节看完了,前面的知识点都学过好多遍了,都通用,重点在后边,不知道有谁象我这样的学习,这是非常非常不好的习惯,要坚持看完,看完多练多总结!不多说了,说多了都是泪。)为了弥补这多年的坑,最后一次看壁虎老师的视频了,也就是把java基础学完了,以后再也不看他视频了,浪费时间,直接看笔记回忆快。可以考虑看看其他老师的视频,每个人的学习方法和经历都不一样,更可况其他老师的教学方式也不一样,多看一个老师的,说不定你获得的知识也不一样;
现在把这些知识点都总结下,与大家分享。---故这篇文章适合看过51自学网壁虎老师的视频的同学
先来简介下这个java基础的由来:壁虎老师当时在51自学网录制这个视频的时候才17岁,还是边学边教的,点击率现在应该破千万了把!(我是12年注册51自学网的,当时大学有java这么课程,我还二十多岁了,还以为壁虎老师是个经验丰富的编程高手,想不到啊!)我是最近搜索才知道,他是前印象笔记的程序员,现在是高手了应该,也自己开课了,我去看了他最近一两年做的视频,每集五六分钟的风格,感觉还是没有以前好了,就像他自己说的,只有初学者讲出来的才适合初学者听,经验丰富的其实以为你基础都已经懂了。我也是百度才知道这些的。
好了,基本情况介绍完了,壁虎老师的课程讲了啥,我截图了,实战6-18至6-31都木有看,木有什么技术含量,我只记知识点。我们只通过代码去回忆所学过的知识点。
现在开始:
A6_1 ~ A6_4 (略!)只是简单介绍,跳过
A6_4 创建类与对象(最近没看该集,直接跳过)
public class A6_4{ //这个是一个A6_4(第6章第4节)的类
public static void main(String[] args){
Person MyPerson=new Person(); //这Person人,就是对象,new创建一个MyPerson的对象
MyPerson.name="小明放到"; //这个对象叫小明
System.out.println(MyPerson.name);
MyPerson.eat();
}
}
A6_5 面向对象与内存解析
public class A6_5{
public static void main(String[] args){
Person One=new Person();//新建一个one对象,储存在一个位置
Person Two=new Person();//新建另一个two对象,储存在另一个位置
Two.age=12;//这个two对象从它之中去age空间并赋值
System.out.println(Two.age);
System.out.println(One.age);
One.eat();//这个one对象从one之中去eat空间并赋值
Two.eat();//这个two对象从two之中去eat空间并赋值
}
}
A6_6 有参无返回间的调用(最近没看该集,直接跳过)
public class A6_6{
public static void main(String[] args){//main函数,一般用来测试
Person per=new Person();
int age=per.getAge(18);//age()中有参,18就是参数
System.out.println(age);
}
}
A6_7 有参无返回间的调用(最近没看该集,直接跳过)
public class A6_7{
public static void main(String[] args){
Test MyTest=new Test();//无参
System.out.println(MyTest.name);
}
}
A6_8 无
A6_9 return和多参方法
class Dog{
String name;
public String print(String n,int a,char b){
System.out.println("n="+n);
System.out.println("a="+a);
System.out.println("b"+b);
return n;//返回方法制定的类型值,这个值总是确定的,可以把n改“sdsd”字符串
}
public void str(int a){
if(a==0){
System.out.println("你好");//不会输出,因为下面有return
}else if(a==1){
return;//结束方法的执行,“你好”、“我很好”都不会输出
}
System.out.println("我很好");//不会输出,因为上面有return
}
}
public class A6_9{
public static void main(String[] args){
Dog A=new Dog();
A.print("小明",12,'男');//调用print方法的三个参数
}
}
/*编译结果:
n=小明
a=12
b男
*/
A6_10 toString方法
//在java中,所有对象都有toString()这个方法
class Cat{
String name;
int age;
public String toString(){//不定义toString方法的话,输出的不是内容,而是输出内存地址
return "我的姓名:"+name+"我的年龄:"+age;
}
}
//哈希码值:对象的内存地址
public class A6_10{
public static void main(String[] args){
//String name=new String("你好");
//sysSystem.out.println(name);//同等于sysSystem.out.println(name.toString);
Cat one=new Cat();
one.name="小明";
one.age=12;
Cat two=new Cat();
two.age=16;
two.name="小红";
System.out.println(one);//默认调用.toString相当于one.toString
System.out.println(two);//默认调用.toString相当于two.toString
}
}
/*编译结果:
我的姓名:小明我的年龄:12
我的姓名:小红我的年龄:13
*/
A6_11 this关键字
class Cat{
String name;
int age;
String color;
public void set(String name,int age,String color){
this.name=name;//有this为成员变量
this.age=age;
this.color=color;
}
public String toString(){
return "姓名:"+name+"\t年龄:"+age+"\t颜色:"+color;
}
public Cat abc(){
return this;//当前对象的引用
}
}
public class A6_11{
public static void main(String[] args){
Cat one=new Cat();
Cat two=new Cat();
one.set("第一只猫",5,"黑色");
two.set("第二只猫",6,"紫色");
Cat three=new Cat();
three=two.abc();//把two返回abc()赋值给three
//three=two;
System.out.println(one);
System.out.println(two);
System.out.println(three);
}
}
/*编译结果:
姓名:第一只猫 年龄:5 颜色:黑色;
姓名:第二只猫 年龄:6 颜色:紫色;
姓名:第二只猫 年龄:6 颜色:紫色;
*/
A6_12 理解封装
//封装:不想给别人看的进行封装,可以告诉的就公开
class Student{
private String name;//private私有的,加这个只能在自己的类访问它,其他类不能访问,即不想告诉别人,隐藏起来
private int age;
private char gender;//
//给gender提供一个共有的方法setGender,也就是可以公开的方法
public void setGender(char gender){//命名规范,看到set开头就知道给成员属性做设置
if(gender=='男'||gender=='女'){//增加控制用户乱输入,即只能输入男或女,不能输入其他内容
this.gender=gender;
}else{
System.out.println("请输入正确的性别");//输入其他内容就提醒
}
}
//不能直接输出了,需要定义一个方法
public char getGender(){//命名规范,看到get开头取得意思
return this.gender;//return gender;可以这么写,因为没有重名,加个this容易分清
}
}
public class A6_12{
public static void main(String[] args){
Student one=new Student();
//one.gender('f');这个是没有加private前可以直接传值,加private后还这么写就会报错
one.setGender('男');
System.out.println(one.getGender());
}
}
A6_13 方法重载
import java.util.Arrays;//数组的排序
//重载指在一个类中有相同的名字,但是参数不同的多个方法,调用时根据参数不同的参数列表选择对应的方法
class Student{
//max方法名一样方便记忆,只要参数不一样就行
public void max(int a,int b){//两个int类型
System.out.println(a>b?a:b);//a>b?a:b三元运算符,判断a是否大于b,大于选择a,否则选择b
}
public void max(double a,double b){//两个double类型
System.out.println("第二个方法"+(a>b?a:b));
}
public void max(double a,double b,double c){//三个double类型
double max=a>b?a:b;
System.out.println("第三个方法"+(max>c?max:c));//max>c?max:c记得加括号,否则计算机识别错误
}
}
public class A6_13{
public static void main(String[] args){
double[] arr={43.5,5.46,61.5,7.6,7.8};//根据参数的不同自动选择哪个方法,这个是double
Arrays.sort(arr);//数组排序,Arrays中有很多方法名都是sort,就是参数不一样
for(int i=0;i<arr.length;i++){
System.out.println(arr[i]);
}
}
}
A6_14 构造函数方法
/*
构造方法(构造函数):使用new+构造方法创建一个新的
构造函数是定义在java类中的一个用来初始化对象的函数
构造函数与类同名没有返回值
Student one=new Student()
*/
class Cat{
private String name;
private int age;
//Cat()其实就是构造方法,与类同名,没有viod
Cat(String name,int age){//有参的构造方法,
this.name=name;
this.age=age;
//System.out.println("姓名"+this.name+"年龄"+this.age);
}
Cat(){//无参的构造方法,若没有定义构造方法,系统默认创建一个,就是不会执行任何操作
}
//加viod和返回值都是普通的方法get(),不能被new调用到
void get(){
System.out.println(this.name);
}
}
public class A6_14{
public static void main(String[] args){
Cat one=new Cat();//调用无参的构造方法
one.get();
Cat two=new Cat("小花",2);//有参的构造方法,new出来就有小花属性了
two.get();
}
}
/*编译结果:
null
小花
*/
A6_15 ~ A6_31 (略!)
A6_32构造代码块
public class A6_32{
public static void main(String[] args){
Person A=new Person();//调用无参构造方法
Person B=new Person("小李");//调用有参构造方法
System.out.println(A.country);
System.out.println(B.country);
}
}
/*特点:
对象一建立就运行了,而且优先于构造函数执行
作用:给对象进行初始化的
构造代码块和构造方法的区别:
构造方法是对应的对象进行初始化,
构造代码块是给所有的对象进行统一的初始化(每个要调用的构造方法,先执行构造代码块)
构造代码块中定义是不同对象共性的初始化内容
*/
class Person{
String name;
String country;
Person(){//无参构造方法
System.out.println("我是无参构造方法");
}
Person(String name){//有参构造方法
this.name=name;
System.out.println("我是有参构造方法");
}
//构造代码块,无需调用,直接输出,请看特点,很少用到,面试可能有问道
{
country="我是构造代码块";
}
}
A6_33构造函数之间的调用
public class A6_33{
public static void main(String[] args){
//Student S=new Student("小花",12);
Student B=new Student("fd");
}
}
/*
this:看上去,用来区分局部变量和成员变量同名的情况
this:就是代表本类对象,this代表它所在函数(方法)所属对象的引用
构造函数之间的调用只能通过this语句来完成
构造函数之间进行调用时this语句只能出现在第一行,初始化要先执行,如果初始化当中还有初始化,那就去执行更细节的初始化
*/
class Student{
String name;//成员变量
int age;
Student(){
System.out.println("无参构造方法");
}
Student(String name){//局部变量
this();//调上面的构造方法,
this.name=name;//有this的是成员变量
System.out.println("fdfd");
}
Student(String name,int age){
this(name);//调上面的构造方法,this相当于new Student(name),即
this.age=age;//相当于B.age=age
}
}
A6_34 Static关键字
/*
static关键字
作用:是一个修饰符,用于修饰成员(成员变量,成员方法)
1.被static 修饰后的成员变量只有一份(大家共享)
2.当成员被static修饰之后,多了一种访问方式,除了可以对象调用之外,还可以被类直接调用(类名.静态成员)
static的特点:
1.随着类的加载而被加载
2.优先于对象的存在
3.被所有的对象所共享的
4.可以直接被类名所调用
存放位置
类变量随着类的加载而存在于data内存区
实例变量随着对象的建立而存在于堆内存。
生命周期:
1.类变量生命周期最长,随着类的消失而消失
2.实例变量生命比类变量短,它是随着对象的消失而消失
方法注意事项:
1.静态的方法只能访问静态的成员(不能防范局部变量)
2.非静态的方法既能访问静态的成员(成员变量,成员方法)也能访问非静态成员
3.静态的方法中是不可以定义this super关键字
因为静态优先于对象存在,所以静态方法不可以出现this
*/
A6_34
public class A6_34{
public static void main(String[] args){
Student A=new Stydent();
A.country="中国";
Student B=new Stydent();
System.out.println(b.country);
Student.print();
}
}
class Student{
String name;
int age;//实例变量
static String country;//静态变量(类变量),把大家都有的属性单独拿出来,生内存,存放在静态区(data:数据区、共享区、方法区)
static void print(){
//String AA=“hello”;//数据局部变量,前面不能加static
System.out.println(name);
}
void p(){
System.out.println(country);
}
}
A6_37 静态的应用范围
/*什么时候使用静态
static所修饰的内容是成员(成员变量,方法)
从两方面入手:
什么时候使用静态的成员变量:
当属于同一个类的所有对象出现共享数据时,
需要将存储这个共享数据的成员变量用static修饰
什么时候使用静态方法
当功能内部没有访问到非静态的成员时(对象特有的数据)
那么该功能可以定义成静态的
*/
public class A6_37{
public static void main(String[] args){
Person A=new Person();
A.name="姚明";
Person B=new Person();
B.name="小明";
A.print();
B.print();
}
}
class Person{
String name;//实例成员
static String country;//静态成员
void print(){//访问非静态,
System.out.println(name+"您好");
}
}
A6_38 main方法
/*
主函数(主方法)
1.public (访问修饰符,公共的)代表该类或者该函数访问权限是最大的
2.static 代表主函数随着类的加载就已经存在了
3.void 代表主函数没有具体的返回值
4.main main不是java中的关键字,它是一个特殊的单词,
它能够被JVM(java虚拟机)所识别
5.String[] args 函数的参数,参数类型是一个字符串数组
,该数组的元素是字符串
*/
public class A6_38{
public static void main(String[] a){
for(int i=0;i<a.length;i++){
System.out.print(a[i]);
}
}
}
A6_39 练习-静态工具类
/*
静态应用工具类
每一个应用程序都有共性的功能,
可以将这些功能进行抽取,独立封装。以使复用
对象的作用:对象是用来封装数据的,
只要这个类里面有非静态的成员时,
那对象就必须存在。
*/
public class A6_39{
public static void main(String[] args){
int[] arr={232,43,535,343,23,43,3,4};
int[] arr1={34,43,232,34344};
System.out.println(ArrayOperate.max(arr));
}
}
A6_42 静态代码块
/*
静态代码块
格式:
static{
静态代码块中执行语句
}
特点:随着类的加载而执行,并且只会执行一次,并且还优先于主函数。
作用:用于给类进行初始化(构造代码块是给成员初始化)
*/
class Person{
static{
System.out.println("我是静态代码块");
}
{
System.out.println("我是构造代码块");
}
}
class A6_42{
public static void main(String[] args){
Person n= new Person();
Person m= new Person();
}
}
A6_43 对象初始化过程
class Student{
static{
System.out.println("我是静态代码块");
}
{
System.out.println("我是构造代码块");
}
void print(){
System.out.println("我是普通方法");
}
private String name;
private static String country;
}
public class A6_43{
public static void main(String[] args){
Student s=new Student();
}
}
/*
1.因为new Student()用到了Student类,所以会把它从硬盘上加载进入内存
2.如果有static静态代码块就会随着类的加载而执行,
还有静态成员和普通方法也会随着类的加载而被加载
3.在堆中开辟空间,分配内存地址
4.在堆中建立对象特有属性,并同时对特有属性进行默认初始化
5.对属性进行显示初始化
6.执行构造代码块。对所有对象进行初始化
7.执行对应的构造函数,对对象进行初始化.
8.将内存地址给S(给栈中的变量)
*/
A6_44单例设计模式
/*
设计模式:针对此类问题最有效的解决方法
java23种设计模式
单例设计模式:解决一个类只在内存中存在一个对象
如何让一个类在内存中只存在一个对象?
1.禁止其他的应用程序,通过此类来创建对象
2.既然外部不能通过此类创建对象了,我们要用对象,
就可以再本类里面创建本类对象。
3.为了其他应用程序能够访问到本类里面创建的对象,
我需要对外界提供一种访问方式
如何用代码体现出来:
1.私有化构造方法
2.在本类中创建本类对象
3.对外界提供访问的方法
*/
class Person{
String name;
private Person(){}
static Person p=new Person();//下面的事静态static
public static Person getInstance(){//静态要调用,所有必须为静态
return p;//这个get是静态,返回p也是静态
}
}
public class A6_44{
public static void main(String[] args){//静态
Person A=Person.getInstance();//调用静态,静态只能调用静态,
A.name="小明";
Person B=Person.getInstance();
System.out.println(B.name);//输出小明,说明和A调用同一个对象
}
}
/*输出结果:
小明
*/
A6_45继承1
/*
继承
继承的概述:
1.提高了代码复用性,简化了代码
2.让类与类之间产生了继承关系,才有了后面的多态特性的存在
注意:千万不要为了获取其他类的功能简化代码,而建立继承关系,
必须要类与类之间存在继承关系, 继承关系:is a
*/
//父类,超类,基类
//子类,导出类
Person{
String name;
int age;
}
class Student extends Person{
void study(){
System.out.println("学习");
}
}
class Teather extends Person{
void teath(){
System.out.println("教书");
}
}
A6_46继承2
/*
继承概述_2
子类拥有父类的成员,子类不能拥有父类中被private修饰后的成员
java多层继承 在多层继承中最下层的子类拥有整个继承体系的成员,
最上层的父类里面定义所有子类的共性描述
java中不支持多继承,只支持单继承。因为多继承存在安全隐患,
当多个父类定义了相同的成员,子类对象不确定运行哪一个。
java保留这种机制,并用了另一方式来体现 多实现(如接口)
*/
class A{
String name;
void show(){
}
}
class B{
int age;
void show(){
}
}
class C extends A{//不支持多继承
}
class D extends C{//D有C的属性,同时也有A的属性
}
class A6_46{
public static void main(String[] args){
C c=new C();
c.show();
}
}
A6_47 子父类中的成员变量
/*子父类成员特点
成员:
1.成员变量
2.函数
3.构造函数
变量:
this 代表当前对象的引用 this.变量 首先在本类中找所需要的这个变量,
如果没有找到再父类中找。
super 用于访问当前对象的父类成员,super.变量 直接父类中找所需变量
*/
class Person{//父类
String name="张三";
}
class Student extends Person{//子类,继承父类
String name="李四";
void show(){
System.out.println(super.name);//super先去父类找,要是用this先在本类找(输出李四)
}
}
public class A6_47{
public static void main(String[] args){
Student stu=new Student();
stu.show();//调用shoe()方法
}
}
/*输出结果
张三
*/
A6_48子父类中的函数
/*
动物
猫,狗
当子类中出现和父类中一样的函数时,当子类对象调用该函数,
运行的是子类中的函数,如同父类中的函数被覆盖了一样,
这种情况就是函数的另一种特性:重写(覆盖)
注意:
1.子类覆盖父类时,必须要保证子类权限大于等于父类,才可以覆盖,否则编译出错
访问权限修饰符:public> default>private 成员前面没加任何访问权限
修饰符默认权限就是default
2.静态的函数只能覆盖静态的
记住:
重载:只看同名的方法的参数列表,如,父类是run()方法、子类是run(String a),存在的参数不同,方法名都一样
重写:子父类方法要一模一样,如都是run()方法,方法名参数都一样
*/
class Animal{//父类
String Type;
public void run(){//不写public就默认default,现在是public
System.out.println("跑步中");
}
}
class Cat extends Animal{
}
class Dog extends Animal{
//String Type="大黄狗";//不加String说明要用父类的Type,这样会报错,加String是重新定义Type
public void run(String a){//要加public,否则权限比父类方法小,就不能重写(覆盖),现在public等于父类的,可以覆盖
Type="大黄狗";//要写在run()方法中,因为这个Type是Animal中的变量,写在外面是重新定义
System.out.println(Type+"哼着歌跑步中");//因为这个类不想用父类的方法,所有需要重写,如:狗不想这样跑步,要哼着歌
}
}
public class A6_48{
public static void main(String[] args){
Cat C=new Cat();
C.run();
Dog d=new Dog();
d.run();
d.run("dd");
}
}
A6_49继承中的构造函数
/*
有了子父类之后构造函数的特点:
在对子类对象进行初始化的时候,
父类的构造方法也会运行,那是因为子类的构造函数默认
第一行
有一条隐式的语句 super();每个子类构造方法都有
子类每个构造方法第一行都有一个隐式的 super();
*/
class fu{//父类
String name;
fu(){//无参
System.out.println("父类构造方法");
}
fu(String n){//有参
this.name=n;
System.out.println("父类有参构造方法");
}
}
class zi extends fu{//子类
zi(){//无参
//super();//不写也会默认有这个,所有先访问父类
System.out.println("子类构造方法");
}
zi(String n){//有参
//super();//构造方法的第一句不写也会默认有这个,所有先访问父类,
//注意这个super()是无参,所以访问的事父类的无参构造方法
//要调用父类的有参构造方法,那就用super(“小李”);
this.name="小李";
//super();不能写在这个位置,会报错,只能在构造方法的第一句
System.out.println("子类有参构造方法");
}
}
public class A6_49{
public static void main(String[] args){
zi z=new zi("小李");//调用子类有参的构造方法
}
}
/*输出结果:
父类构造方法
子类有参构造方法
*/
A6_50对象转型
/*
对象的转型:
1.对象的向上转型 子类转成父类 默认进行 父类引用指向子类对象
2.对象的向下转型 父类转成子类 强制进行 如:Cat c=(cat)a
关键字:instanceof 测试左边的对象是否是右边类的实例
如果是返回true 不是返回false
*/
class Animal{//父类,动物
void sleep(){
System.out.println("睡觉中");
}
}
class Cat extends Animal{//子类,猫
void catchMouse(){
System.out.println("捕鼠");
}
}
class Dog extends Animal{//子类,狗
}
public class A6_50{
public static void main(String[] args){
Cat a=new Cat();
System.out.println(a instanceof Cat);//输出为trun,
System.out.println(a instanceof Dog);//会报错,猫和狗它们没有关系,只能和Animal有关系
Animal a=new Cat();//向上转型,
System.out.println(a instanceof Cat);//输出为trun,猫是动物是实例(上面是cat()赋予了a)
Animal a=new Animal();
System.out.println(a instanceof Cat);//输出为false,动物不能说是猫,有可能是狗
System.out.println(a instanceof Dog);//输出为false,同理
/*向上转型和向下转型的区别*/
Animal a=new Cat();//向上转型,a是猫,当做动物看待
a.sleep();//可以,猫看成动物,所有能访问父类
a.catchMouse();//不可以,a已经当做动物看了,动物不能看成猫,不能访问子类(猫)独有的方法
Dog d = (Dog)a//a是猫,编译不会报错,运行就会报错,因为a猫的类型不能给b狗
Cat c=(cat)a;//向下转型,a是当做动物看待(父类),要当做猫看(即待转成子类),
c.catchMouse();//能访问父类
c.sleep();//也能访问子类
}
}
A6_51多态的概述
/*
OOP三大特性:封装,继承,多态
多态:可以理解为事物存在的多种体现形态
动物:猫, 狗, 猪 (猫是动物,动物也有猫)
人: 男人 女人 (一个男人我可以称之为人,一个女人我也可以称之为人)
1.多态的体现
父类引用指向子类对象
2.多态的前提
(1)必须得类与类之间存在关系,可以是继承关系 也可以是实现关系
(2)必须得有重写 //要是Dog没有重写,编译不会报错,因为Dog也会访问Animal,此时多态没有意义
3.多态的好处
大大提高了程序的可扩展性(不做很大的修改就多很多功能)
4.多态的弊端
提高的程序可扩展性,只能用父类的引用,访问到父类中成员(向上转型:缺点是只能看到Animal里面共性的,看不到其他的)
多态成员变量的特点:
1.编译期间:参阅的是引用型变量所属的类中是否有调用的方法
2.运行期间:参阅对象所属的类中是否有调用的方法
*/
class Animal{
/*要是没有这个。下面的function(Animal c)会报错
void sing(){
System.out.println("唱歌");
}
*/
}
class Dog extends Animal{
void sing(){//重写
System.out.println("汪汪的唱歌");//对动物唱歌不满意,所以要重写汪汪的唱歌
}
}
class Cat extends Animal{
void sing(){
System.out.println("喵喵的唱歌");//同理重写
}
void catchMouse(){
System.out.println("捕鼠");
}
}
public class A6_51{
public static void main(String[] args){
Cat c=new Cat();
function(c);
Dog d=new Dog();
function(d);
Pig p=new Pig();
function(p);
//可以继续接着来几种动物都可以,不用每个动物都写 function,用function(Animal c)即可
}
/**每个动物要唱下歌,都要对应写多个封装,太麻烦,所以不用
public static void function(Cat c){//封装
c.sing();
}
public static void function(Dog d){//封装
d.sing();
}
*/
//要是Dog没有重写,编译不会报错,因为Dog也会访问Animal,此时多态没有意义
public static void function(Animal c){//封装,把c自己看成动物,其他动物可以访问
//Animal c=new Cat();//A——50对象转型章节:向上转型,主要访问共性(父类)内容,向下转型,父类子类都可以访问
Cat c1=(Cat)c;//需要向下转型
c1.catchMouse();//向上转型,只能看到父类的成员,单写这个会报错,所以需要上面的转型
}
}
A6_51多态的概述_1
/*
OOP三大特性:封装,继承,多态
多态:可以理解为事物存在的多种体现形态
动物:猫, 狗, 猪 (猫是动物,动物也有猫)
人: 男人 女人 (一个男人我可以称之为人,一个女人我也可以称之为人)
1.多态的体现
父类引用指向子类对象
2.多态的前提
(1)必须得类与类之间存在关系,可以是继承关系 也可以是实现关系
(2)必须得有重写 //要是Dog没有重写,编译不会报错,因为Dog也会访问Animal,此时多态没有意义
3.多态的好处
大大提高了程序的可扩展性(不做很大的修改就多很多功能)
4.多态的弊端
提高的程序可扩展性,只能用父类的引用,访问到父类中成员(向上转型:缺点是只能看到Animal里面共性的,看不到其他的)
多态成员变量的特点:
1.编译期间:参阅的是引用型变量所属的类中是否有调用的方法
2.运行期间:参阅对象所属的类中是否有调用的方法
*/
class Animal{
/*要是没有这个。下面的function(Animal c)会报错
void sing(){
System.out.println("唱歌");
}
*/
}
class Dog extends Animal{
void sing(){//重写
System.out.println("汪汪的唱歌");//对动物唱歌不满意,所以要重写汪汪的唱歌
}
}
class Cat extends Animal{
void sing(){
System.out.println("喵喵的唱歌");//同理重写
}
void catchMouse(){
System.out.println("捕鼠");
}
}
public class A6_51{
public static void main(String[] args){
Cat c=new Cat();
function(c);
Dog d=new Dog();
function(d);
Pig p=new Pig();
function(p);
//可以继续接着来几种动物都可以,不用每个动物都写 function,用function(Animal c)即可
}
/**每个动物要唱下歌,都要对应写多个封装,太麻烦,所以不用
public static void function(Cat c){//封装
c.sing();
}
public static void function(Dog d){//封装
d.sing();
}
*/
//要是Dog没有重写,编译不会报错,因为Dog也会访问Animal,此时多态没有意义
public static void function(Animal c){//封装,把c自己看成动物,其他动物可以访问
//Animal c=new Cat();//A——50对象转型章节:向上转型,主要访问共性(父类)内容,向下转型,父类子类都可以访问
Cat c1=(Cat)c;//需要向下转型
c1.catchMouse();//向上转型,只能看到父类的成员,单写这个会报错,所以需要上面的转型
}
}
A6_53多态的练习
/*俄罗斯方块,每种都有好几个形状再变化,如长字型有:横、竖*/
import java.util.Random;//随机数,随机变化
//定义方块的类型:山字型、L字型、Z字型、长字型、田字型
class FK{//方块父类
void bx(){
System.out.println("变形");
}
}
class FK_szx extends FK{//山字型
void bx(){//变形方式不满意,在重写
System.out.println("山字型在变形");
}
}
class FK_lzx extends FK {//L字型
void bx(){//同理,重写
System.out.println("L字型在变形");
}
}
class FK_zzx extends FK{//Z字型
void bx(){//同理,重写
System.out.println("Z字型在变形");
}
}
class FK_cfx extends FK{//长方型
void bx(){//同理,重写
System.out.println("长方型在变形");
}
}
class FK_tzx extends FK{//田字型
void bx(){//同理,重写
System.out.println("田字型在变形");
}
}
//有继承,有重写,有父类指向子类的对象(都有父类的共性),所以用多态,这些都是前提
class A6_53{
public static void main(String[] args){
Random r=new Random();//随机数对象
int a=r.nextInt(5);//产生一个随机数用a接收下
FK fk=null;//用多态方法,父类,没有指向任何对象
switch(a){
case 0://随机数为0,以下同理
/*非多态的写法(下同),代码好多看起来都一样,所以用多态优化以下
FK_szx szx=new FK_szx();
szx.bx();//每次调用变形的方法(父类)都一样,所以用多态方法改写
break;
*/
fk=new FK_szx();//产生山字型形状赋给了父类fk,fk父类指向子类FK_szx的对象,以下同理
break;
case 1:
/*非多态的写法(下同)
FK_lzx lzx=new FK_lzx();
lzx.bx();
break;
*/
fk=new FK_lzx();
break;
case 2:
/*非多态的写法(下同)
FK_zzx zzx=new FK_zzx();
zzx.bx();
break;
*/
fk=new FK_zzx();
break;
case 3:
/*非多态的写法(下同)
FK_cfx cfx=new FK_cfx();
cfx.bx();
break;
*/
fk=new FK_cfx();
break;
case 4:
/*非多态的写法(下同)
FK_tzx tzx=new FK_tzx();
tzx.bx();
break;
*/
fk=new FK_tzx();
break;
//****再多都可以写,不用太大改动*****提高程序的可扩展性
}
/*
通俗理解:动物园管理员叫动物来吃饭,至少动物具备吃饭的行为(否则无意义),
跑过来一只猫就按照猫的吃法(猫怎么吃它就怎么吃),跑过来一只狗就按照狗的吃法(狗怎么吃它就怎么吃)
*/
fk.bx();//父类指向哪个就用哪个,通用都有bx()变形的方法
}
}
A6_54 匿名对象
/*
匿名对象:没有名字的对象
匿名对象的使用方式之一:当对对象的方法只调用一次时,我们可以用匿名对象来完成
,比较简化。
匿名对象的使用方式之二:匿名对象可以被当做实参传递
*/
class Car{
String color;
void start(){
System.out.println("汽车被开动");
}
}
public class A6_54{
public static void main(String[] args){
// Car c=new Car(); 一般的做法,把地址转给c
//new Car().start();这个就是匿名对象,不转地址
//new Car().color=“蓝色”;改变属性值这个没有意义,因为不只调用一次
print(new Car());//匿名对象调用有参方法,简写
/*相当于
Car c=new Car();
print(c);
*/
}
static void print(Car c){//有参
c.start();//被调用
}
}
A6_55Object类toString()
/*
一个特殊的类
Object:它是java中所有对象的直接或者间接父类,根父类(基类),
它里面定义的功能时所有对象都应该具备的
Object的类有哪些在API里面找(JAVAAPI.CHM文本网上有下载)
记住:当定义一个新类时,没有指明要继承某类,它默认继承Object类
*/
class Animal{//也默认继承Object类
}
class Cat{//没有指明要继承的父类,默认继承Object类,
//要是写了extends Animal,就不会继承Object类,也会有toString,因为继承的Animal父类也默认继承Object,里面含有toString
public String toString(){//不写也会默认有,根据查询API方法名也是这样,所以可以重写toString()
return "你好";//重写了
}
}
class A6_55{
public static void main(String[] args){
/*cat中要是没有toString()
Cat c=new Cat();
System.out.println(c);//输出一个地址,因为Cat类会默认有toString()方法
相当于System.out.println(c.toString());
*/
System.out.println(new Cat().toString());//相当于上面的注释
}
}
A6_56Object类equals()
/*
一个特殊的类
Object:它是java中所有对象的直接或者间接父类,根父类(基类),
它里面定义的功能时所有对象都应该具备的
记住:当定义一个新类时,没有指明要继承某类,它默认继承Object类
==和Object里面的equals其实比较的就两对象的内存地址是否一致
Object类equals()是比较两个对象是否相等
*/
class Cat{
int num;
//Object本身就有了比对的方法了,所以就用equals()
public boolean equals(Object fff){//Object ff=new Cat();向上转型
if(fff instanceof Cat){//instanceof判断,是不是猫,否则C2是狗,编译会报错
Cat ee =(Cat) fff;//向下转型,是猫就转型
return this.num==ee.num;//this相当于当前对象的引用
}else{
return false;//猫和狗本来就不匹配,所以返回false
}
}
}
class Dog{
}
public class A6_56{
public static void main(String[] args){
Cat c = new Cat();//C是猫
Dog C2 = new Dog();//C2是狗
System.out.println(c.equals(c2));
//System.out.println("ff".equals("ff"));//ff是对象,可以直接调用方法,equals相当于被重写过的
}
}
A6_57 final关键字
/*
final(最终)是一个修饰符
1.final可以修饰类,函数,变量(成员变量,局部变量)
2.被final修饰后的类不可以被其他类继承
如:
final class Person{}//final修饰
clsaa Student extends Person(){}//编译报错,Person已经被final修饰
3.被final修饰后的函数不可以被重写
如:
class Person{
final void show(){//final修饰
System.out.println("你好")
};
}
clsaa Student extends Person(){//Person没有被final修饰,这个可以继承
void show(){//不能重写,因为show()方法被final修饰
System.out.println("世界")
};
}
4.被final修饰后的变量不允许被再次赋值,final在对变量进行修饰时一定赋值,
如:
final int a=34
a=52;//报错,不能被重写赋值
5.被final修饰后的变量我们称它常量,常量不能被改变
6.被public final static 多个修饰符修饰的变量我们称它为:全局常量,
如:
public final static String STUDENT_NAME="小李";
注意:常量的命名规范:字母全部要大写,如:final String NAME=“小王”;
如果这个名字是由多个单词组成,在单词之间用_隔开,如:final String STUDENT_NAME="小李";
*/
class Student{
public final static String STUDENT_NAME="小李";//全局常量,被final修饰后都是常量
}
public class A6_57{
public static void main(String[] args){
Student s=new Student();//输出被final修饰的值
Student s1=new Student();//和上一个一样的值,浪费空间,没必要
}
}
A6_58 抽象类
/*
abstract:是一个修饰符
可以修饰方法,类
1.当我们多个类存在相同的功能,但是功能的主体不同,这时我进行向上抽取
只抽取功能的定义不抽取功能的主体
抽象类的特点:
1.抽象方法一定要在抽象类中
2.抽象类和抽象方法必须要被abstract关键字修饰
abstract只能修饰类和函数
3.抽象的类是不能被创建对象,因为调用抽象的方法没意义
4.抽象类的中方法要被使用,必须由子类重写抽象类中的方法
,然后创建子类对象来调用
5.抽象类中可以定义非抽象的方法,有时我们需要此类不能被new关键字创建对象时,
可以用abstract将此类变成抽象类。
6.子类如果只重写一部分的抽象方法,那么该子类还是一个抽象类,如果抽象类的方法
要被使用,子类必须重写抽象类中的所有方法。
值得注意:抽象类和普通的类没有太大的不同。
1.抽象类无法同过new关键字创建对象
2.抽象类里面可有抽象的方法
*/
abstract class Animal{//抽象类,不能new对象来调,如不能:Animal t=new Animal();,但是可以supe创建对象
abstract void sing();//方法少了大括号,大括号内容都被重写了,留着没有意义void sing();就这么写,看到不懂得方法就用加abstract,
abstract void show();
}
class Cat extends Animal{
void sing(){
System.out.println("喵喵唱歌");
}
void show(){//猫类重写了,狗类等其他的子类也要重写
}
}
class Dog extends Animal{
void sing(){
System.out.println("汪汪唱歌");
}
void show(){//统一都要重写
}
}
public class A6_58{
public static void main(String[] args){
Animal t=new Cat();//多态,向上转型,可以接受
t.sing();
}
}
A6_60模板方法设计模式
/*
需求:求一段代码运行所花费时间
原理:结束时间-开始时间 System.currentTimeMillis()
什么是模板方法设计模式?
定义功能时,功能的一部分是确定(印章是模板),而确定的部分在使用不确定(用什么颜色的墨水),
那么这时就得将不确定的部分暴露出去,由该子类去完成。
举例:造冰激凌的机器就是模板,这是确定的,造多大。不确定的是你给我什么材料,什么奶油我就造什么味的
*/
//编译生成class发给用户,用户自己写段代码,利用你的方法测用户自己写的代码运行所花的时间,不能写死
abstract class Demo{//对应下面的抽象abstract,一个类出现了抽象的方法,那个类也要变成抽象
public final void getTime(){//final防止被覆盖,因为用户不一定知道
long start =System.currentTimeMillis();//1秒=1000毫秒
function(); //默认this.function();子类对象就是当前对象 这里相当于把Test类方法写在这里,也就是要运行的代码,要是写在这里就是写死了
long stop =System.currentTimeMillis();
System.out.println("共花费了"+(stop-start));
}
public abstract void function();//不确定你要对哪些代码所花费的时间,所以要补写public void function(){}就变成空的方法无意义,就变成抽象的方法
}
//这块是用户自己重写,其他的目的是测这块代码所花费的时间
class Test extends Demo{//子类对象
public void function(){//Test类方法
for(int i=0;i<1000;i++){//为了效果更明显,用for循环
System.out.print("f");//求这段代码运行所花费的时间,输出1000个f
}
}
}
public class A6_60{
public static void main(String[] args){//静态方法可以通过类名来访问
Test t=new Test();
t.getTime();
}
}
A6_61接口(一)
/*
接口:初步理解,接口是一个特殊的抽象类,当抽象类中全部是抽象方法时,
可以通过接口的形式来体现。
class 用于定义类
interface 用于定义接口
接口中成员的格式:
1.public static final String NAME="小李";//全局常量,public static final这三个修饰符位置可以随便放
2.public abstract void show(); //抽象方法
注意:
1.接口中只能出现public 访问修饰符,(不能加其他,如:private,会报错的)
2.接口不可以创建对象,因为里面有抽象方法,需要被子类实现(接口叫实现,不叫重写),子类对接口中的所有抽象方法实现后,子类才能够实例化,否则子类就是一个抽象类
*/
interface smoket{//接口
public static final String NAME="小李";//接口中三个修饰符不写也会默认加,接口中没有成员变量
//int a = 0;默认会加上public static final这些修饰符,所以属于全局常量,不是成员变量
public abstract void show();//public、abstract不写会默认加的
//接口没有构造方法/函数,抽象类有构造方法/函数(不能通过new关键字来创建对象),
}
class Student implements smoket{//类之间是继承关系,接口是实现关系,把接口的抽象方法要实现
public void show(){//类似重写的方法,不写abstract,
System.out.println("在吸烟");
}
}
public class A6_61{
public static void main(String[] args){
Student s=new Student();
s.show();
}
}
A6_62接口(二)
/*
java不支持多继承,因为存在安全隐患,当父类中定义了相同功能,
功能内容不同时,子类不确定要运行哪一个
但是java保留了这种机制,并用另一种体现形式来完成表示>>多实现
一个类可以实现多个接口(java虽不支持多继承,但也以另一种形式保留了,接口)
关系:
类与类之间:继承关系extends
接口与类之间:实现关系implements
接口与接口之间:继承关系extends
*/
interface Smoket{//接口
public abstract void smoket();//是public
}
interface Game extends Smoket{//接口与接口之间:继承关系
public abstract void computerGame();//要被重写
}
class Student implements Smoket,Game{//接口与类之间:实现关系,多接口之间要逗号隔开
public void smoket(){//不写public,因为接口中是public不能低于
System.out.println("吸烟");
}
public void computerGame(){//要重写,不然要报错
System.out.println("游戏");
}
}
public class A6_62{
public static void main(String[] args){
/*
Student s=new Student();
s.smoket();
s.computerGame()
*/
}
}
A6_63接口练习
/*
通俗理解:以前的电脑主板和CPU是焊接在一起,要是不满意CPU就连主板一起换掉,现在技术先进了,主板和CPU提供接口,可以单独换CPU即可。
接口和多态两者的区别:
接口:提高了我们功能的扩展性 ,
通俗理解:电脑没有USB接口是可以的,还可以运行,但是就不能扩展硬盘,要换原装硬盘,装新的,旧的要丢掉
因为它降低事物与事物之间的耦合性(关系紧密程度,就是焊接在一起,谁也不能拆散我们)
通俗理解:有什么好处,就是共同开发,你要等我开发玩你才能开始,接口就可以分开做,后面再通过接口
多态:提供我们的程序的扩展性;
父类中定义的是多个类中共性的基本功能
接口中定义的是扩展功能
接口好处:
可以多实现,也就是一个类可以实现多个接口
*/
class Person{//父类中定义的是多个类中共性的基本功能,不能少
String name;
int age;
}
interface Smoket{//接口中定义的是扩展功能,可以不要
public abstract void smoket();
}
class Student extends Person{
}
class Worker extends Person implements Smoket{
public void smoket(){
System.out.print("抽烟");
}
}
public class A6_63{
public static void main(String[] args){
Worker w=new Worker();
w.smoket();
}
}
A6_64 包
/*
包(package)
什么是包呢?可以理解为文件夹
包的作用:
1.对类进行分类管理
2.给类提供了多层命名空间
注意:
1.类名的全称是包名.类名
2.定义包的语句一定要在代码的第一行
*/
package pack;
public class A6_64{
public static void main(String[] args){
System.out.println("你好");
}
}
---------------------------------完,不明白的给我留言·······················