this关键字
当一个对象创建后,Java虚拟机(JVM)就会给这个对象分配一个引用自身的指针,这个指针的名字就是 this。
用法:对当前对象的默认引用 调用自己的的构造方法。
用在构造方法内部,区分同名的成员变量和局部变量;
this(name.age);调用构造方法,减少代码冗余;
可用于调用成员属性和成员方法(调用方法时可以省略)。
public class TestClass
{
int x,y;
void testShow(int x,int y){
this.x=x; //this.x 就是我们上 int x,y;中的x 。=x是我们传来的x
this.y=y;
}
}
继承中 this 和 super:
假如父类中有一个方法是 add()
子类没有重写父类的方法,super.add() 和this.add() 都是调的父类的方法, 没什么区别,如果重写了this.add()就默认调本类的方法,super就默认调父类的方法。
再在子类中,都不写的话,如果有重写父类的add()方法的话就默认调本类的add()方法, 如果本类没有重写就调父类的方法。
static关键字:
用法: 修饰成员变量,表示静态变量(类变量),可以被更改,所有实例对象共享;
修饰方法,表示静态方法(类方法);
可用类或实例对象调用,一般只用类调用。
static定义的属性一旦被某一个实例化对象更改,则其余对象调用的为更改后的值;
static修饰的变量一旦写入便生成空间,默认值为0,其他对象只有实例化后才被分配空间。
类的加载和对象实例化:
构造方法:创建类的对象时定义的初始化状态,无返回值,不能用void修饰,命名必须和类名相同。
不能被直接调用,只能在new运算符在创建对象时被自动调用,在定义一个类时,java编译器会自动生成一个无参构造函数。
普通方法:命名可以和构造方法相同,但必须带返回值,在程序执行到它时被调用。
public class Demo4 {
public static void main(String[]args){
System.out.println(A.instance.num2);
System.out.println(new A(1).num2);
}
}
class A{
static A instance=new A(1);
static int num1=5;
int num2;
A(int num3){
num2=num1-num3;
}
}
//用第一种方法调用时,A与num2均先开辟空间,在执行newA(1)时,5还未赋值给num1;
//执行后num1赋值为5;
//num1默认值为0.0-1=-1;
//用第二种方法调用时,先实例化了一个A对象,此时,num1=5,5-1=4.
静态块:
public class Test {
public Test() {// 构造方法
System.out.println("我是构造方法,创建对象的时候我会执行,我执行完,对象就造出来了");
}
static {
System.out.println("我是静态块,类加载的时候我就执行了,而且只执行这一次");
}
}
然后这样:
new Test();
new Test();
当创建Test类的一个对象的时候,比如new Test() ,是这样,首先是类加载,然后才能new对象,静态块在类加载的时候就执行了,这就说明静态块在new对象之前就会执行,而且一个类在第一次被使用的时候会被加载,然后在整个应用程序的生命周期当中不会再次被加载了,就加载这一次,所以这就说明,静态块就执行一次,不会执行第二遍!
对象的实例化:
创建对象:Student stu1 = new Student();
实例对象:Student stu2 = new Student("张三",21,"男");
可以看出实例对象调用了Student类的构造方法,为创建的对象赋了值,
而创建对象只是创建了一个对象。
程序阅读训练:
new A类.B方法(); 实例化一个对象并调用B方法
实例方法可调用静态方法或静态变量;
静态方法不可调用实例方法;
静态方法中不能有非静态的方法或变量。
继承:
在Java 术语学中,被继承的类叫超类(superclass ),继承超类的类叫子类(subclass )。子类是超类的一个专门用途的版本,它继承了超类定义的所有实例变量和方法,并且为它自己增添了独特的元素。
语法:单根继承(接口可实现多继承),一个子类只能继承一个类,一个类可以有多个子类。
super:在子类中通过super调用父类的属性和行为;
super表示父类对象。
class Fu{
}
class Zi extends Fu{
}
子类不能继承父类的显式定义的构造方法,若想要继承父类的构造方法,需要通过覆盖该构造方法,并在方法中通过super调用父类的该构造方法的方式来继承。
继承的三种情况说明:
1、父类中没有显式定义任何构造方法,此时父类中实际有一个默认的无参数构造方法。这时,在子类中显式定义任何构造方法时,可以不用使用super调用父类的默认方法。
2、父类中显式定义了默认的无参数构造方法,那么子类可以定义任意的构造方法,而不必使用super调用父类的构造方法
3、父类中显示定义了构造方法,却没有显示定义默认的无参数构造方法,那么子类定义任何构造方法中都需要通过super调用父类的构造方法
import和package:
包名写法规范:域名倒置 即 公司名.项目名.模块名.子模块名...
语法---打包命令
javac-d.Table.java
package oop3
package oop2
a.通过全类名引用
oop2.类名+实例化对象=new oop2.类名();
b.直接导包
import+包名.类名;
import+包名.*;表示导入与此包中相关的所有类。
Java.lang 包:
是Java语言的核心类库,包括了运行Java程序必不可少的系统类,如基本数据类型、基本数学函数、字符串处理、线程、异常处理类等。每个Java程序运行时,系统都会自动地引入java.lang包,所以这个包的加载是缺省的。
访问修饰符:
为了程序的安全,需要访问修饰符
a. public:同一类,同一包中的子类,不同包的子类,其他包的类均可访问。
b.protected:同一类,同一包的子类,不同包中的子类
c.default:默认(可省)同一类或同一包中的类可访问。
方法的重写:
方法的重写也称为方法的覆盖(override),对于某一个子类而言,他的方法与其父类的方法内容不尽相同。
条件:方法名称相同,参数特征完全相同,返回值类型相同;
访问修饰符范围不能缩小;
子类重写父类方法,没有继承,则不存在重写;
子类方法不能抛出比父类更大的异常。
public class TestStaticMethodExtends {
public static void main(String[] args) {
A a = new B(); //父类类型指向子类对象。
a.p(); //调用子类p方法。
}
}
class A {
public static void p() {
System.out.println("基类");
}
}
class B extends A {
public static void p() {
System.out.println("子类");
}
}
程序绑定:
概念:绑定指的是一个方法的调用与方法所在的类(方法主体)关联起来。对java来说,绑定分为静态绑定和动态绑定;或者叫做前期绑定和后期绑定
动态绑定:在运行时根据具体对象的类型进行绑定。
栈区 | 方法栈 | 堆区 |
动态绑定的过程:
虚拟机提取对象的实际类型的方法表;
虚拟机搜索方法签名;
调用方法。
父类类型指向子类对象:
Animal a=new Animal();
Tiger t=new Tiger();
Animal a2=new Tiger();
Tiger t=new Animal(); //错误写法,不能使子类对象指向父类实例
引用对象 实例化对象
a | ------------------> | new Animal() |
t | ------------------> | new Tiger() |
a2 | ------------------> | new Tiger() |
实例代码(来源网络):
public class Father {
public void method() {
System.out.println("父类方法,对象类型:" + this.getClass());
}
}
public class Son extends Father {
public static void main(String[] args) {
Father sample = new Son();//向上转型
sample.method();
}
}
声明的是父类的引用,但是执行的过程中调用的是子类的对象,程序首先寻找子类对象的method方法,但是没有找到,于是向上转型去父类寻找静态绑定:
概念及用法:
在程序执行前方法已经被绑定,此时由编译器或其它连接程序实现。例如:C。
针对java简单的可以理解为程序编译期的绑定;这里特别说明一点,java当中的方法只有final,static,private和构造方法是前期绑定在处理java类中的成员变量时,并不是采用运行时绑定,而是一般意义上的静态绑定。所以在向上转型的情况下,对象的方法可以找到子类,而对象的属性还是父类的属性。
Java当中只有final(无子类),static,private和构造方法是静态绑定。
示例代码(来源网络)
public class Father {
protected String name="父亲属性";
public void method() {
System.out.println("父类方法,对象类型:" + this.getClass());
}
}
public class Son extends Father {
protected String name="儿子属性";
public void method() {
System.out.println("子类方法,对象类型:" + this.getClass());
}
public static void main(String[] args) {
Father sample = new Son();//向上转型
System.out.println("调用的成员:"+sample.name);
}
}
结论,调用的成员为父亲的属性。
toString和instance of:
一切对象皆Object类。
public class A extends Object{}
Object中的toString()方法:
Object中的toString()方法返回一个字符串,该字符串由类名(对象为该类的一个实例)、“@标识符”和此对象的哈希码的十六进制表示组成。
Object类中的toString()方法是打印类命和内存地址的。
比如String类就重写了Object的toString()方法.
如果一个object类里的成员有
String str;
float a;
int b;
String tostr;
tostr = new Object().str;这样才是得到Object类的str的值
但是Object是没有这个属性的.当你要得到一个类中的一个非static类型的属性的时候,你要得到它的值可以用
new 类名().属性名 来得到。
用System.out.println()输出一个对象的时候,java默认调用对象的toString()方法
一般要覆盖这个方法,这样根据覆盖逻辑就可以输出自己的对象
比如定义一个类User,有id,name属性,你直接输出一个user对象的话
System.out.println(user),得到的只是
全限定名@地址首地址
如果在User类里面覆盖这个toString方法的话就能输出你要的
比如
public String toString(){
return "user name is:"+this.name+";"+"user id is:"+this.id;
}
这样你输出一个user对象就是
User user = new User(1,"zhangshan");
System.out.println(user);
得到:user name is :zhangshan;user id is: 1;
instanceof 关键字:
java 中的instanceof 运算符是用来在运行时指出对象是否是特定类的一个实例。instanceof通过返回一个布尔值来指出,这个对象是否是这个特定类或者是它的子类的一个实例。
A instanceof B 表示A是B的一个实例对象。
用法:
result = object instanceof class
参数:
Result:布尔类型。
Object:必选项。任意对象表达式。
Class:必选项。任意已定义的对象类。
说明:
如果 object 是 class 的一个实例,则 instanceof 运算符返回 true。如果 object 不是指定类的一个实例,或者 object 是 null,则返回 false。
final关键字:
用法:
当某个类不想被继承时
当某个方法不想被重写时
当某个变量值不想被更改时给final修饰的变量赋值:定义时赋值;初始化块;构造方法。
final String STR=“hello”;
public final void hello(){
}
static final String STR =“hello”; 静态字符串变量,避免每个实例对象都有一份相同的STR值造成的空间浪费。
类变量被final修饰,为宏变量,程序中用到的“Hello”值全部用STR替换。
命名规范与注释:
类和接口:首字母大写(第一个可以小写)
变量和方法:首字母小写,后面每个单词首字母大写,以字母、下划线或$开头。
包:全小写,域名倒置。
常量:全大写,多个单词之间用下划线“—”相连。
final int AGE;
对象与内存控制:
类的加载顺序:
a.父类静态代码块;
b.子类静态代码块;
c.父类非静态代码块;
d.父类构造函数;
e.子类非静态代码块;
f.子类构造函数; 某一个类初次被加载时,静态块会先执行。
例:
public class ExA {
static {
System.out.println("父类静态代码块。");
}
public ExA() {
System.out.println("父类构造函数。");
}
{
System.out.println("父类非静态代码块。");
}
public static void main(String[] args) {
new ExB();
}
}
class ExB extends ExA {
static {
System.out.println("子类静态代码块。");
}
{
System.out.println("子类非静态代码块。");
}
public ExB() {
System.out.println("子类构造函数。");
}
}
执行结果:父类静态代码块。子类静态代码块。父类非静态代码块。父类构造函数。子类非静态代码块。子类构造函数。
访问子类对象的实例变量:
private int i=22; 先给i分配空间,后赋值为22.
调用被子类重写的方法:
在子类中,用super调用父类的属性和方法。
调用父类无参构造函数:super()
调用父类有参构造函数:super(父类构造方法的参数)
super 为其父类
super.toString() 为调用其父类的toString方法;
static class Parent {
//父类方法
void who() {
System.out.println("I'm parent");
}
}
static class Child extends Parent {
//子类重写方法
@Override
void who() {
System.out.println("I'm child");
}
//通过supper调用父类方法
void parentWho(){
super.who();
}
}
public static void main(String[] args) {
Child child = new Child();
Parent parent = new Parent();
parent.who(); 结果: I'm parent
child.who(); I'm child
child.parentWho(); I'm parent
}
抽象类:
若一个方法无方法主体,在public后有abstract修饰,则该方法是抽象方法,有抽象方法的类称为抽象类。
抽象类不能直接用new实例化。但可以实例化实现了的子类,用父类引用指向子类实例
子类必须继承父类的所有方法,否则子类也是抽象的。
某个类为抽象类,但其中可以无抽象方法。
多态:
对象的向上转型和向下转型:
Tiger t=new Tiger(); 实例化一个Tiger类型t
Animal a=t ; 子类类型实例赋给父类类型对象 即向上转型
子类可以重写父类中的方法,向上转型时,由于子类已经扩充了父类的方法,父类调用的父类的方法已被子类重写,这样 间接的也扩充了父类的功能。
Animal a= new Tiger();父类类型(引用)指向子类对象
Tiger t=(Tiger) a; 子类对象 t 强转Tiger类赋给子类变量 即向下转型,使类型更明确
子类自己的方法无法用继从父类承来的类的实例对象调用,需实例一个子类自己的对象t来调用。
t.eat(); 调用子类特有的方法
向下转型可以调用父类没有定义,但子类实现的方法
比如父类有a()方法,子类重写了a()方法,而且额外添加了一个b()方法,父类中没有b方法
那么要调用子类的b方法,必须将父类变量向下转型为子类才可以调用b方法
A a=new B();
B b1=(B)a; a.fun1(); a.fun2(); b1.fun3(); 子类调用从父类继承的方法,利用多态可以直接调用。而fun3是子类自己的方法,使用父类定义的对象是没有办法调用的,所以必须 B b1=(B)a;转换定义类型来进行调用。 |
多态概念:父类的某一种类型在不同子类中表现出不同的形态。
Animal animal=new Monkey();
animal.sleep();
Animal animal=new Tiger();
animal.sleep();
多态的体现:
父类的引用指向了自己的子类对象
父类的引用也可以接收自己的对象
多态的前提 :
必须是类与类之间只有关系,要么继承或实现
通常还有一个前提,存在覆盖
多态的好处:
多态的出现提高了程序的扩展性
多态的弊端 :
只能使用父类的引用访问父类的成员
接口:
使用规则:关键字+接口名称
接口中的所有变量属性为常量。public static final ,可省
接口中定义的全部方法为抽象方法。public abstract,可省
interface transfer Data(object data); void charge();//电流传输 String STR="hello"; //实现USB功能
接口是最高的抽象,,其包含的所有方法都是抽象方法。
在java中,单根继承,但可多实现。
a,接口继承接口
public interface InterfaceA extends InterfaceB { } 接口继承接口可以不实现父接口中的方法,可以声明自己的新方法;
b, 类继承(实现)接口
public class MiChong implments Usb{ } java类可以一次继承多个接口,用implements 接口1,接口2; 类实现接口时,一定要实现接口中声明的方法,如果接口中没有定义抽象方法则不需要,但是要注意,类实现了一个接口A,如
果B是A的父接口,且B中有抽象方法,则该类必须实现A和B中的所有抽象方法;
抽象方法只能定义在抽象类中,抽象类实现接口,可以不实现接口中的抽象方法。
c,继承加实现
public class KingSD extends A implement Usb,Istore{ }
集合概述:
父接口 Collection
子接口: List 列表 Set
ArrayList:
List接口中的一个实现类。
java.util→Collection→List→ArrayList→add(E,O)
接口 实现类 一个方法
------------------------------ |
------------------------------- |
------------------------------- |
------------------------------- |
------------------------------- |
实质为数组形式 ,便于查找元素。
LinkedList:
List接口中另一个实现类 List→LinkedList
实质为链表,链表结构的集合类,便于修改增删频繁的情况
泛型初步:
用途:
List personList=new ArrayList(); personList.add(person); add中参数为Object类型,可以add任何一个对象 personList.add(tiger);系统会默认为集合中全为person类 List<Person> personList=new ArrayList<erson>()//泛型,此时返回值是Person类型 而不是Object类型 personList.add(person1); personList.add(tiger);//编译报错 泛型将运行时风险转变成为编译期异常。
泛型语法定义:
public class Person<T>{ //Person类中全为T证件 private String pname; private T card;//证件 }
Set接口:
HashSet为Set的一个实现类。
Set不是线性结构,是以map方式存储。Set中元素按其哈希码存储,每个元素有其固定位置,不可有重复元素。
Set中无get[i]方法。
package set; import java.util.HashSet; import java.util.Set; public class Demo01 { public static void main(String[]args){ Set<String> set=new HashSet<String>();//创建一个参数为字符串的容器 set.add("ton"); set.add("lina");// System.out.println(set.size()); /*下来进行其元素的迭代*/ /*for(int i=0;i<set.size();i++){ set.get(i);在Set中无get这个方法 }*/ //第一种迭代,增强for循环 for(String str:set){ System.out.println(str); } //第二种迭代,转换成数组形式 Object[]objArr=set.toArray(); for(int i=0;i<objArr.length;i++){ System.out.println(objArr[i]); } }//第三种迭代:迭代器Iterator }
hashcode和equals:
equal方法用于判断对象内容是否相同;hashcode判断对象放置的位置是否相同。
Iterator迭代器:
接口:Iterator<E>
主要方法:hasNext() 判断指向的下一个位置是否还有元素
next() 返回迭代的下一个元素
remove() 从迭代器指向的集合中移除元素
iterator() Iterator中方法的总称
package set; import java.util.HashSet; import java.util.Iterator; import java.util.Set; public class Demo02 { public static void main(String[]args){ String p1="猫"; String p2="狗"; String p3="兔子"; Set <String>set = new HashSet<String>(); set.add(p1); set.add(p2); set.add(p3); System.out.println("----------------"); //Iterator Iterator<String> itor = set.iterator(); while(itor.hasNext()){ String str = itor.next(); System.out.println(str); }
TreeSet:
当中的元素有序。
Comparable接口:
TreeSet具有排序能力。
如果其元素类型是String,则根据字母先后顺序排序。
如果是Integer,则按数字大小来排。
如果是用户自定义类型如Person,则须告诉集合你的排序规则。
Comparable 表示可排序,要表明Person是可排序的。
缺点:排序规则单一。
public class Person inplements Comparable<Person>{ //compareTO() }
//compareTO()方法
public int CompareTO(Person o){
if(this.age>o.age){
return 1;
}else if(this.age<o.age){
return -1;
}
return 0;
} //该规则按年龄升序排列。
TreeSet 具有排序功能,但若元素为自定义类,则需先实现接口Comparable并调用其compere To方法说明排序规则。
Comparator接口:
特点:有多种排序规则。
public class AgeDesc inplements Comparator<Person>{
public int Compare(Person o1,Person o2){
if(o1.age>o2.age){
return -1;
}else if(o1.age<o2.age){
return 1;
}
return 0;
} //此方法为按年龄降序排序 AgeDesc为年龄降序去实现Comparator接口。
}
使用时需要进行实例化
Comparator<Person> ageDesc=new AgeDesc();
Set<Person>persons = new TreeSet<Person>(ageDesc);
若要进行身高升序或其他排序方式,则重新定义一个身高升序的类去实现接口Comparator,用主函数(需实例化这个类)进行调用即可。
HashMap:
List:
ArrayList |
LinkedList |
Collection:
List |
Set |
Set:
HashSet |
TreeSet |
Map接口的一个实现类。Map(K,V )
Map接口的一些方法:
返回map中的值
TreeMap:
容器中元素有序排列。可以对key进行有序排列。
异常语法:
try-catch
try-catch-......catch
try-catch......final 无论是否发生异常 final中的内容都会执行
try-final
异常是程序执行过程中一种不正常的情况,通过try-catch语法对其处理,使程序继续向下运行。
异常语法中的一个类及其两个子类:Throwable
Exception(异常)<—RuntimeException<—ArithemeticException、Nullpointerexception... |
Error (系统严重错误) |
先捕获具体的异常,后捕获宽泛的异常。
package yichangyuf; public class Hello { public static void main(String[]args){ try{ int num1 = 9; int num2 = 0; @SuppressWarnings("unused") int NUM = num1/num2; }catch(ArithmeticException ex){ System.out.println("it's ok!"); } } }
throws:
在方法的定义时使用,表明该方法有危险,调用需谨慎。
则在调用的时候需要try-catch处理。
1、调用危险方法时,当场处理。
public class Hellooo{ public static void main(String[]args){ A a = new A(); //1、调用危险方法时,当场处理 try{ a.hello(); }catch (IOException ex){ ex.printStackTrace(); } } } class A{ public void hello() throws IOException{ System.out.println(); } }
2、调用危险方法时,将异常上抛给调用者
ublic class Hellooo{ public static void main(String[]args) throws IOException{ A a = new A(); //2、异常上抛给定义者 a.hello(); } } class A{ public void hello() throws IOException{ System.out.println(); } }
throw:
public class Hellooo{ public static void main(String[]args) throws IOException{ B b = new B(); b.hello(); } } class B{ public void hello(){ System.out.println("hello world!"); try{ throw new IOException();//在内部引爆了一个炸弹 }catch(Exception ex){ } } }
向上抛出更大的异常
class B{ public void hello() throws Exception{ System.out.println("hello world!"); //try{ throw new IOException();//在内部引爆了一个炸弹 //}catch(Exception ex){ } }
自定义异常:
特定情况下的异常
class MyException extends Exception{
}