本文主要是介绍java基础(2),对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
面向对象:当需要实现一个功能的时候,不关心具体的步骤,而是找一个已经具有该功能的人,来帮助我做事。(偷懒)
面向过程:当需要实现一个功能的时候,每一个具体的步骤都要亲历亲为,详细处理每一个细节。
打印数组: JDK提供给我们一个Arrays类,其中有一个toString方法,直接就能把数组变成想要的格式的字符串Arrays.toString(数组名字)
面向对象对象思想更符合我们的思考习惯,能把复杂的事情简单化,并将我们从执行者变成指挥者。(封装、继承、多态)
类是相关属性和行为的集合。 类是抽象的,对象是具体的
成员变量是直接定义在类当中的,在方法外边。 成员方法不要写static关键字。
通常情况下,创建一个类不能直接使用,需要根据类创建一个对象,才能使用。(引用类型一般使用步骤也是如此)
1.导包:也就是指出需要使用的类在什么位置。 import 包名称.类名称;(对于和当前类属于同一个包的情况,可以省略导包语句不写)
(只有java.lang包下的内容不需要导包,其他的包都需要import语句)
2.创建
3.使用,分为两种情况:
使用成员变量:对象名.成员变量名
使用成员方法:对象名.成员方法名(参数)
对象内存图: 首先从方法区中将main方法放到栈(压栈)运行;在堆创建对象,从方法区中复制一份成员变量,放到堆中,赋给成员变量默认值;堆成员方法中存放在方法区中的地址;根据栈中的变量名地址找到堆中成员变量赋值,根据栈方法名地址先去堆中找地址,再根据堆中地址去方法区中找方法,运行完成的成员方法,成员变量会立刻出栈。
当一个对象作为参数,传递到方法当中时,实际上传递进去的是方法的地址值。
当使用一个对象作为方法的返回值时:返回值其实就是对象的地址值。
成员变量与局部变量的区别:
1.定义位置:
局部变量定义在方法的内部。
成员变量定义在类中,方法外部
2.作用范围不一样:局部变量在方法当中才可以使用,出了方法就不能用;成员变量:整个类全都可以使用。
3.默认值不一样:
局部变量没有默认值,如果想使用,必须手动进行赋值。
成员变量如果没有赋值,会有默认值,规则和和数组一样。
4.内存的位置不一样:局部变量位于栈内存,成员变量位于堆内存
5.生命周期:局部变量:随着方法进栈而诞生,随着方法出栈而消失; 成员变量:随着对象创建而诞生,随着对象的销毁而销毁。
面向对象三大特征:封装、继承、多态
1.封装在java中的体现:方法是一种封装,关键字private是一种封装。封装就是将一些信息隐藏起来对外不可见。
间接访问private成员变量,就是定义一对儿Getter/Setter方法。必须叫setXxx或者getXxx命名规则。
对于Getter来说,不能有参数,返回值类型和成员变量对应。
对于Setter来说,不能有返回值,参数类型和成员变量对应。
对于基本类型中的boolean值,Getter方法一定要写成isXxx的形式,而SetXxx规则不变。
当方法的局部变量和类的成员变量重名的时候,根据“就近原则”,优先使用局部变量,如果需要访问本类当中的成员变量,需要使用格式:this.成员变量名
【【构造方法】】
构造方法是专门用来创建对象的方法,当我们通过关键字new来创建对象时,其实就是在调用构造方法,格式:
public 类名称(参数类型 参数名称){ 方法体 }
注意事项:1.构造方法方法名称与类名完全相同 2.不能写返回值类型,包括void 3.构造方法不能return一个具体的返回值
4.如果没编写任何一个构造方法,那么编译器将会默认赠送一个构造方法,没有参数,方法体中什么都没有。
一个标准的类通常要拥有下面四个组成部分:
1.所有的成员变量都要使用private关键字修饰
2.为每一个成员变量编写一对Getter/Setter方法
3.分别编写一个无参的构造方法和全参的构造方法
这样的标准类也叫做 Java Bean
Code》Generate(Alt+Insert) 自动生成Getter/Setter方法和构造方法
API使用方法:看包路径,看构造方法,看成员方法
Scanner sc=new Scanner(System.in); //System.in 代表从键盘进行输入
获取键盘输入的一个int数字:int num=sc.nextInt();
获取键盘输入的一个字符串:String str=sc.next();
匿名对象的方式: int num=new Scanner(System.in).nextInt();
匿名对象还可以作为方法参数传入和方法返回值传出
用 Random 生成随机int数字(范围是int所有范围,有正负两种) Random r=new Random();
获取一个int数字(参数代表范围,左闭右开区间),int num =r.nextInt(3) 实际上代表的含义是:[0,3)
数组的长度不可以发生改变,但是ArrayList集合的长度是可以随意变化的。
对于ArrayList 来说,有一个尖括号<E>代表泛型。
泛型,也就是装在集合当中的所有元素全都是什么类型。
泛型只能是引用类型,不能是基本类型。
从JDK1.7开始,右侧的尖括号内部可以不写内容,但是<>括号本身还是要写的。ArrayList<String> list=new ArrayList<>();
public boolean add(E e):向集合当中添加元素,参数的类型和泛型一致;对于ArrayList集合来说,add添加动作一定是成功的,所以返回值可用可不用。但是对于其他集合(今后学习),不一定成功。
public E get(int index):从集合中获取元素,参数是索引编号,返回值就是对应哪个位置的元素。
public E remove(int index):从集合当中删除元素,参数是索引编号,返回值就是被删除掉的元素。
public int size(): 获取集合的尺寸长度,返回值是集合中包含的元素个数。
从JDK 1.5+开始,支持自动装箱、自动拆箱。 char>>Character int>>Integer
java.lang.String类代表字符串:java程序中所有的字符串字值(如"abc")都作为此类的实例实现
字符串的特点:
1.字符串的默认值用不可变 2.正是由于字符串的默认值不可改变,所以字符串是可以共享使用的。 3.字符串效果上相当于char[]字符数组,但是底层原理是byte[]字节数组。
创建字符串:(3+1)
三种构造:public String() public String(char[] array) public String(byte[] array)
一种直接:String str="Hello";
对于引用类型来说,==进行的是地址值的比较;双引号写的字符串在常量池当中(JDK1.7后常量池放在堆中),new出的不在池当中。
如果需要堆字符串的内容进行比较,可以使用两个方法:
public boolean equals(Object obj):参数可以是任意对象,只有参数是一个字符串并且内容相同的才会给true,否则返回false
注意:Object可接收任何对象; equals具有对称性; 如果比较,一个常量,一个变量,推荐把常量字符串写在前面双方。 如果变量写在前面如果为null会发生NullPoinerException.
public boolean equalsIgnoreCase(String str): 忽略大小写,进行内容比较。
String 当中与获取相关的常用方法:
public int length()
public String concat(String str)
public char charAt(int index):获取指定索引位置的单个字符。(索引从0开始)
public int indexOf(String str):查找参数字符串在本字符串当中首次出现的索引位置,如果没有返回-1。
字符串的截取:
public String substring(int index):截取从参数位置一直到字符串末尾,返回新字符串。
public String substring(int begin,int end):截取从begin开始,一直到end结束,中间的字符串。[begin,end)
String当中与转换相关的常用方法:
public char[] toCharArray():将当前字符串拆分成字符数组作为返回值。
public byte[] getBytes(): 获取当前字符串底层的字节数组。
public String replace(CharSequence oldString,CharSequence newString);将所有出现的老字符串替换成新的字符串,返回替换之后的结果新字符串。
分割字符串的方法 :
public String[] split(string regex):按照参数的规则,将字符串切分成若干部分。
注意事项:
split方法的参数其实是一个“正则表达式”,如果按照英文"."进行拆分,必须写成“\\.”(两个反斜杠)
一旦用了static关键字,那么这样的内容不再属于对象自己,而是属于类的,所以凡是本类的对象,都共享同一份。
静态变量:类名称.静态变量
静态方法:类名称.静态方法()
如果没有static关键字修饰,那么必须首先创建对象,然后通过对象才能使用它。
如果有,那么不用创建对象对象就可以直接通过类名调用,也可通过对象名调用(不推荐,不好辨别是不是静态方法,在编译之后也会被javac翻译成为”类名称.静态方法名()“)
注意事项:
1.静态不能直接访问非静态。
原因:内存中现有的静态内容,后有的非静态内容。
2.静态方法中不能用this
原因:this代表当前对象,通过谁调用的方法,谁就是当前对象。
static修饰的成员变量在方法区中的静态区
静态代码块:当第一次用到本类时,静态代码块执行的唯一一次;静态内容总是优先于非静态,所以静态代码块比构造方法先执行。static{}
静态代码块的典型用途:用来一次性地对静态成员变量进行赋值。
java.util.Arrays是一个与数组相关的工具类,里面提供了大量的静态方法,用来实现数组常见的操作。
public static String toString(数组):将参数数组变成字符串(按照默认格式:[元素1,元素2,元素3...])
public static void sort(数组):按照默认升序(从小到大)对数组的元素进行排序。
如果是数值,sort默认按照升序从小到大;如果是字符串,sort默认按照字母升序;如果是自定义的类型,那么这个自动的类需要有Comparator或者Comparable接口的支持。
java.util.Math类是数学相关的工具类,里面提供了大量的静态方法,完成与数学相关的操作。
public static double abs(double num): 获取绝对值,有多种重载。
public static double ceil(double num):向上取整
public static double floor(double num): 向下取整
public static long round(double num):四舍五入(返回值没有".")
Math.PI代表近似的圆周率常量(double)
起点位置-10.8应该转换为-10,两种办法:
1.可以用Math.ceil方法,向上(正方向)取整
2.强转为int,自动舍弃所有小数位。
【【继承】】
继承中成员变量的访问特点:
在父类的继承关系当中,如果成员变量重名,则创建子类对象时,访问有两种方式:
直接通过子类对象访问成员变量 :等号左边是谁(的引用),就优先用谁,没有则向上找。
间接通过成员方法访问成员变量 :该方法属于谁,就优先用谁,没有则向上找。
继承中成员方法的访问特点:
在父子类的继承关系中,创建子类对象,访问成员方法的规则: 创建的对象是谁,就优先用谁,如果没有则向上找。
无论是成员方法还是成员变量,如果没有都是向上找父类,绝对不会向下找子类。
区分ang子类方法中重名的三种变量:
局部变量: 直接写成员变量名
本类的成员变量:this.成员变量名
父类的成员变量:super.成员变量名
重写(Override):“方法的名称一样,参数列表也一样。覆盖、覆写
重载(Overload):方法的名称一样,参数列表不一样。
方法的覆盖重写特点:创建的是子类对象,则优先用子类方法。(new的是谁用的就是谁)
注意事项:
1.必须保证父子类之间的方法名称相同,参数列表也相同。@Override:写在方法前,用来检测是否有效的正确覆盖重写,这个注解就算不写,只要满足要求,也是正确的方法覆盖重写。
2. 子类方法的返回值必须 小于等于 父类方法的返回值范围;Object是所有类的父类。
3.子类方法的权限必须 大于等于 父类方法的权权限修饰符 public>protected>(default)>private
继承关系当中,父子类构造方法的访问特点:
1.子类构造方法当中有一个默认隐含的”super()“调用,所以一定是先调用的父类构造,后执行的子类构造。
2.子类构造可以通过super关键字来调用父类重载构造。
3.super的父类构造调用,必须是子类构造方法的第一个语句,不能一个子类构造调用多次super构造。
4.只有子类的构造方法才能调用父类的构造方法。
总结: 子类必须先调用父类构造,不写则赠送super();写了则用写的指定的super调用,super只能有一个,还必须是第一行。
super关键字用来访问父类内容,super关键字的三种用法:
1.在子类的成员方法中,访问父类的成员变量。
2.在子类的成员方法中,访问父类的成员方法。
3.在子类的构造方法中,访问父类的构造方法。
而this关键字用来访问本类内容,也有三种用法:
1.在本类的成员方法中,访问本类的成员变量。
2.在本类的成员方法中,访问本类的另一个成员方法。
3.在本类的构造方法中,访问本类的另一个构造方法。
在第三种用法中要注意:
A.this(...)也必须是构造方法的第一个语句,唯一一个。
B.super和this两种构造调用,不能同时使用。
在同一个类中,Java普通方法的互相调用可以省略this+点号,而直接使用方法名+参数。因为Java编译器会帮我们加上。
Java语言是单继承,一个类的直接父类只能有唯一一个。可以多级继承;一个父类可以有多个子类。
如果父类当中的方法不确定如何进行{}方法体的实现,那么这就应该是一个抽象方法。
抽象方法:就是加上abstract关键字,然后去掉大括号,直接分号结束。
抽象类:抽象方法所在的类,必须是抽象类才行。在class之前加上abstract即可。
抽象方法只在抽象类中,抽象类中可以有普通成员方法。抽象类中,不一定含有抽象方法。
如何使用抽象类、抽象方法:
1.不能直接创建new抽象类对象。
2.必须用一个类来继承抽象父类。
3.子类必须覆盖重写抽象父类当中所有的抽象方法。(或者子类也是抽象方法)
覆盖重写(实现):子类去掉抽象方法的abstract关键字,然后补上方法体大括号。
4.创建子类对象进行使用。
将鼠标方法抽象子类红线处,Alt+回车选择implement methods,自动将抽象父类相关方法打印出来。
接口是多个类的公共规范,是一种引用数据类型,最重要的内容是其中的抽象方法,
如何定义一个接口的格式:public interface 接口名称(){ //接口内容}
备注:换成了关键字之后,编译生成的字节码文件仍然是:.java --> .class
如果是java 7,接口中可以包含的内容:1.常量 2.抽象方法
如果是java 8 ,还可以额外包含有:3.默认方法 4.静态方法
如果是java 9,还可以额外包含有: 5.私有方法
在任何版本的Java中,接口都能定义抽象方法。
格式: [public] [abstract] 返回值类型 方法名称(参数列表);
注意事项:
1.接口当中的抽象方法,修饰符必须是两固定的关键字:public abstract
2.这两个关键字修饰符,可以选择性地省略。
3.方法的三要素,可以随意定义。
接口的使用步骤:
1.接口不能直接使用,必须有一个“实现类”来"实现"该接口。
格式:
public class 实现类名称 implements 接口名称{ //... }
2.接口的实现类必须重写(实现)接口中所有的抽象方法。实现:去掉abstract关键字,加上方法体大括号。
3.创建实现类对象,进行使用。(实现类名字建议在接口名后加Impl来命名)
默认方法格式:
[public] default 返回值类型 方法名称(参数列表){ 方法体 }
备注:接口当中的默认方法,可以解决接口升级的问题。
1.接口的默认方法,可以通过接口实现类对象,直接调用。
2.接口的默认方法,也可以被接口实现类进行覆盖重写。
接口当中定义静态方法格式:
public staitc 返回值类型 方法名称(参数列表){ 方法体 }
提示 :就是将abstract或者default换成static即可,带上方法体。
注意事项:不能通过接口实现类的对象来调用接口当中的静态方法。
正确用法: 通过接口名称,直接调用其中的静态方法。
格式: 接口名称.静态方法名(参数);
问题:我们需要抽取出一个共有方法,来解决两个默认方法之间重复代码的问题,但是这个共有方法不应该让实现类使用,应该是私有化的。
解决方案:
从Java 9开始,接口中允许定义私有方法:
1.普通私有方法,解决多个默认方法之间重复代码问题。
格式:private 返回值类型 方法名称(参数列表){ 方法体 }
2.静态私有方法:解决多个静态方法之间重复代码问题(只有接口自己才能使用,不能被实现类或者别的类调用)
格式:private static 返回值类型 方法名称 (参数列表){方法体}
常量:接口中也可以定义”成员变量“,但是必须使用 public static final 三个关键字进行修饰
格式:public static final 数据类型 常量类型=数据值;
注意事项:1.接口当中的常量可以省略 public static final 三个关键字,注意,不写也是这样。
2.接口当中的常量必须进行赋值 3.接口当中常量的名称,使用完全大写的字母,用下划线进行分隔。
在Java 9+版本中,接口的内容可以有:
1.成员变量其实就是常量;
2.接口中最重要的就是抽象方法。
格式:[public ][abstract] 返回值类型 方法名称(参数列表);
使用接口的时候,需要注意:
1.接口是没有静态代码块和构造方法的。
2.一个类的直接父类是唯一的,但是一个类可以同时实现多个接口。
格式:public class MyInterfaceImpl implements MyInterfaceA,MyInterfaceB{//覆盖重写所有抽象方法}
3.如果实现类所实现的多个接口当中,存在重复的抽象方法,那么只需要覆盖重写一次即可。
4.如果实现类没有覆盖重写所有接口当中的所有抽象方法,那么实现类就必须是一个抽象类。
5.如果实现类所实现的多个接口当中,存在重复的默认方法,那么实现类一定要对冲突的默认方法进行覆盖重写。
6.一个类如果直接父类当中的方法,和接口当中的默认方法产生了冲突,优先使用父类当中的方法。
1.类与类之间是单继承的,直接父类只有一个。
2.类与接口之间是多实现的,一个类可以实现多个接口。
3.接口与接口之间是多继承的。
注意事项:
1.多个父接口当中的抽象方法如果重复,没关系重写覆盖一次就好。
2.多个父接口当中的默认方法如果重复,那么子接口必须进行默认方法的重写覆盖。【而且带着default关键字】
【【多态】】
extends继承或者implements实现,是多态性的前提;一个对象有多种形态,这就是对象的多态性
代码当中体现多态性,其实就是 父类引用指向子类对象。
格式: 父类名称 对象名=new 子类名称(); 或者 接口名称 对象名=new 实现类名称();
访问成员变量两种方式:
1.直接通过对象名称访问成员变量;看等号左边是谁,优先用谁,没有则向上找。
2.间接通过成员方法访问成员变量,看该方法属于谁,优先用谁,没有则向上找。
在多态的代码当中,成员方法的访问规则是: 看new的是谁,就优先用谁,没有则向上找。
口诀: 成员变量:编译看左边,运行还看左边; 成员方法:编译看左边,运行看右边。
父类引用指向子类对象,如果访问子类有而父类没有的方法: obj.methodZi();//错误写法
多态好处:无论右边new出来的时候换成哪个子类对象,等号左边调用方法都不会改变。
1.对象的向上转型其实就是多态写法,向上转型一定是安全的,从小范围转向了大范围。
向上转型也有弊端:对象一旦向上转型为父类,那么就无法调用子类原本特有的内容。解决方案:用对象的向下转型【还原】
2.对象的向下转型,其实是一个【还原】动作
格式: 子类名称 对象名 =(子类名称)父类对象;
含义: 将父类对象,【还原】成为本来的子类对象;
Animal animal=new Cat();//本来是猫向上转型成为动物
Cat cat=(Cat)aniaml;//本来是猫已经被当成动物了,换回来成为本来的猫。
注意事项:
a.必须保证对象本来创建的时候,就是猫,才能向下转型为猫。
b.如果对象创建的时候本来不是猫,现在非要向下转型为猫,就会报错。 java.lang.ClassCastExcepion;类转异常
类似于: int num=(int)10.0//可以 int num=(int)10.5//不可以,精度损失
向下转型要用instanceof进行判断,如何才能知道一个父类引用的对象,本来是什么子类?
格式: 对象 instanceof 类名称
这将会得到一个boolean值结果,也是判断前面的对象能不能当做后面类型的实例。
对象也能自动从子类型转换成父类型,类似于基本类型的自动类型转换: double d=10; 结果d为10.0
native:用来声明本地方法,该方法的实现由非java 语言实现,比如C。一般用于java与外环境交互,或与操作系统交互。
final关键字:
当final关键字修饰一个类的时候,格式: public final class 类名称{// ...}
含义:当前这个类不能有任何子类。(太监)
注意:一个类如果是fianl的,那么其中的成员方法都无法进行覆盖重写(因为没儿子)
当final关键字用来修饰一个方法的时候,这个方法就是最终的方法,也就是不能被覆盖重写,格式:修饰符 final 返回值类型 方法名称(参数列表){} 注意:对于类、方法来说,abstract关键字和final关键字不能同时使用,因为矛盾。
一旦使用final修饰局部变量,那么这个局部变量就不能更改。(只能一次赋值,不能改变)
//final int num=200;
//num=250;//错误
对于基本类型来说,不可变是变量当中的数据不可变;对于引用类型来说,不可变是变量当中的地址值不可改变。
对于成员变量来说,如果使用final关键字修饰,那么这个变量也照样是不可变。
1.由于成员变量具有默认值,所以用了final之后必须手动赋值,不会给默认值了。
2.对于final的成员变量,要么使用直接赋值,要么通过构造方法赋值。二值只能选其一。
3.必须保证类中所有重载的构造方法,都最终会对final的成员变量进行赋值。
四种权限修饰符: private 本类
[default] 同包
protected 同包和子类
public 所有类
【【内部类分类】】
1.成员内部类
格式:
修饰符 class 外部类名称{
修饰符 class 内部类名称{
//..
}
//..
}
注意:内用外,随意访问,外用内,需要内部类对象
内部类编译后的类名称Person$Heart.class
show in explore 打开项目文件夹
Recompile "类名称.java" 重新编译类
==========================================
如何使用成员内部类?两种方法:
1.间接方式:外部类的方法当中,使用内部类;然后main只是调用外部类的方法。
2.直接方式,公式:
【外部类名称.内部类名称 对象名=new 外部类名称().new 内部类名称();】
内部类成员变量如果出现重名,在内部类的方法中:
this.num //访问内部类的成员变量
Outer.this.num //访问外部类的成员变量
2.局部内部类(包含匿名内部类)
定义格式:
修饰符 class 外部类名称{
public 返回值类型 外部类方法名称(参数列表){
class 局部内部类名称{
// ...
}
}
}
小结以下类的权限修饰符:
public>protected>[default]>private
定义一个类的时候,权限修饰符:
1.外部类:public/(default)
2.内部类:public/protected/[default]/private
3.局部内部类:什么都不能写
局部内部类,如果想要访问所在方法的局部变量,那么这个局部变量要求必须是【有效的fianl的】。
备注 从Java8.0+开始,只要局部变量事实不变,那么final关键字就可以省略。
原因:
1.new出来的对象在堆内存当中。
2.局部变量是跟着方法的,在栈内存当中。
3.方法运行结束会立刻出栈,内存变量就会立刻消失。
4.但是new出来的对象会在堆当中持续存在,直到垃圾回收消失。
如果接口的类名称(或者是父类的子类)只需要使用唯一的一次。这种情况下可以省略掉该类的定义,而改为使用【匿名内部类】。
匿名内部类的定义格式:
接口名称 对象名=new 接口名称(){
//覆盖重写接口的所有抽象方法
};
对格式“new 接口名称(){...}”进行解析
1.new代表创建对象的动作 2.接口名称就是匿名内部类需要实现哪个接口 3.{...}这才是匿名内部类的内容
注意问题:
1.匿名内部类在创建对象的时候,只能使用唯一一次。如果希望多次创建对象,而且类的内容一样的话,那么就必须使用单独定义的实现类了。
2.匿名对象,在调用方法的时候,只能调用唯一一次。如果希望同一个对象,调用多次方法,那么就必须给对象起个名字。
3.匿名内部类就是省略了【实现类/子类名称】,但是匿名对象就是省略了【对象名称】。
//使用了匿名内部类,而且省略了对象名称,也是匿名对象。
new MyInterface() {
@Override
public void method1() {
System.out.println("方法三");
}
@Override
public void method2() {
System.out.println("方法四");
}
}.method1();
类和接口都可以作为成员变量类型。任何一种数据类型都可以作为成员变量的类型。
接口可以作为方法的参数和返回值。
这篇关于java基础(2)的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!