ctrl+双击:一个类,即打开这个类的源码
IDEA红色波浪线出错-->Alt+Enter-->显示异常
属性(字段)+ 方法 = 类(class)
静态的属性 动态的行为
面向对象(oop):分类的思维模式,而面向过程是线性思维模式,面向对象是适合多人协作的复杂问题。
oop的本质:以类的方式组织代码,以对象的形式封装数据。
抽象:把多个共同点抽取出来形成一个类。(抽 像)
从认识论分析:是具体对象抽象成类;
但从代码运行角度分析:是由类这样一个模板新建了一个对象。
方法: 修饰符 返回值类型 方法名(……){
方法体
return 返回值;}
public String Hello{
return "hello world";} //return:结束方法,返回一个结果。
静态方法(static)调用:类名.方法名 Student.say();
非静态方法调用:实例化(new)这个类: new Student.say(); 一般写作:
Student student = new Student(); //对象类型 对象名 = 对象值
student.say();
*static方法不能调用非static方法,因为static方法是和类一起加载的,而非静态方法在类实例化(new对象)之后在存在,已经存在的不能调不存在的。*
this:表示当前类。 this.name=name(参数传进来的值);this.age=age;
*一个项目应该只存在一个main方法,其他的public class里面都不要写main。*
Student student = new Student(); (alt+enter,enter)//类的实例化,返回一个自己的对象,student对象就是一个student类的具体实例。可以是Student xiaoming = new Student();也可以是Student xiaohong = new Student(); 即一个类可以产生不同的对象。
构造器:
用idea打开.class文件:Project Structure -> Modules -> +Add根目录 -> out文件 -> OK,Apply
一个类即使什么都不写,它也会存在一个方法,即构造器。(.class文件自动生成一个方法)
构造器的2个特点(无参):①必须和类的名字相同。②必须没有返回值类型,也不能写void。
构造器的作用:①使用new关键字,本质是在调用构造器。(一旦定义了有参构造,无参就必须显示定义) ②用来初始化值(对象的值)
快捷键:alt+insert -> constuctor -> 自动生成有参/无参构造器代码。
自己总结:构造器的作用其实就是用来初始化值,因为在新建对象后会有一个默认值,而构造器的作用就是重写这个默认值。 有参构造在new person(这个括号里"sss"),无参构造在构造器大括号里this.name="sss";
*String预定义类是不可变的,所以就当变量来处理。*
属性的定义:(修饰符) 属性类型 属性名 = 属性值
对象的创建和使用:1.必须使用new关键字创建对象、构造器 Person xiong = new Person();默认有无参构造器(自动生成的)。 2.对象的属性:xiong.name 3. 对象的方法:xiong.sleep()
接口——方法。两个方法相同,则表示方法名和参数列表都相同。
封装:
“高内聚,低耦合” ,针对于属性。高内聚——类的内部数据操作自己完成,不允许外部干涉;低耦合——仅暴露少量的方法给外部使用。
private:(属性)私有。例如:private String name,之后就不可以使用Student s1=new Student();s1.name;调用了。
封装后需要设置get,set方法才可以调用数据:
public void setName(String name){ public String getName(){
this.name=name;} return this.name;}
main方法: main方法:
s1.setName("熊”); sout(s1.getName());
一般都是先set再get,alt+insert自动生成get,set方法
封装的意义:1.提高程序的安全性,保护数据。
2.隐藏代码的实现细节(set方法可以用if语句判断是否满足条件来做一些安全性的判断)
3.统一接口(get,set)
4.提高系统的可维护性。
继承:
extends,扩展。 子类是父类的扩展,子类 extends 父类
继承的都是public的东西,private的东西是无法继承的。
*在Java中,所有的类都默认直接或间接继承object类。*
注意:Java中类只有单继承,没有多继承,直接继承一个,间接继承多个(父子)。
父类有属性:protected String name = "xiong";
子类有属性和方法:private String name = "dan";
public void test(String name){
sout(name); //表示此方法中的属性
sout(this.name); //调此类
sout(super.name);} //调用父类
在应用类里面调用:
import com.oop.student;
public class Application{
psvm{
Student student = new Student();
student.test("熊");
最后输出:
熊
dan
xiong
有关子类父类构造器:
1、子类构造器隐藏代码:调用了父类的无参构造,相当于在构造器里面的第一行默认有一个super();这样new子类时父类的方法也new了。
2、注意调用父类的构造器的话,必须要写在子类构造器的第一行。
3、super();和this();不能同时调用构造方法(都得在第一行,要么调父类的,要么调子类的)。
4、若父类无参构造设置成了有参构造而没有加上无参构造,则子类也无法自动生成无参构造。
/*this();方法:表示本类的构造 super():表示父类的构造
this:代表本身调用者这个对象 super:代表父类对象的引用
this:没有继承也可以使用 super:只能在继承条件下使用*/
方法重写
(子类重写父类的方法):重写都是方法的重写,与属性无关。 非静态方法
快捷键:Alt + insert -> Override Methods
@Override // 有功能的注解,重写
public class A extends B{
public void test() {
super.test(); ---重写自己的---> sout("A=>test()");
}} // B中输出的是"B=>test()"
重写完以后在有psvm的类中调用:
B b = new A(); /* 类名 对象名 =new 类名() 后面的类名是实际类型,前面的类名是引用类型,实际类型是确定的,引用类型可以有父/子类型。*/
b.test(); ------>输出:A=>test() 【若子类父类都是static方法的话输出B=>test()】
原因:静态方法是类的方法,而非静态是对象的方法(static修饰的方法归类所有,叫做类的成员,而不是对象的成员)。有static时,b调用了B类的方法;没有static时,b则调用对象的方法,b是A类new的对象所以调用A的方法。
1、静态方法(public static void test()):方法的调用只和左边(定义的数据类型A/B)有关。
2、非静态方法:只有非静态才能重写(子类重写父类的方法)
3、重写只能都是public,不能有private。
重写注意点:
①必须有继承关系 ②方法名必须相同 ③参数列表必须相同 ④修饰符范围可以扩大但不能缩小:
public>protected>default>private
为什么要重写?
子类不一定需要父类的功能 / 父类的功能不能满足子类的需要
多态:
多态与重写联系紧密。
一个对象的实际类型是确定的,但可以指向的引用类型就不确定了(父类的引用指向子类)
Student s1 = new Student();
Person s2 = new Student(); //如果子类重写了父类的方法,那就执行子类。 Person是父类型,可以指向子类,但是不能调用子类独有的方法。
Object s3 = new Student();
对象能执行哪些方法,主要看对象等式左边的(引用)类型。
s2.eat(); //eat方法在Student里有Person里没有,报红。 -----> 回车: ((student)s2.eat(); //强制转换成student类型。person转student,高转低。
s2.run(); // 若student子类重写了父类Person里的run(),则执行子类的方法。
多态——同一方法可以根据发送对象的不同(student / person)而采用不同的行为方式,重写了执行Student,没有重写执行Person。
多态存在的条件:①有继承关系 【若没有父子关系则出现类型转换异常:ClassCastException】
②子类重写父类方法
③父类引用子类对象 Father f1 = new Son();
不能被重写的方法:1、static方法,属于类,不属于实例。
2、final常量,通过final修饰的类也不能被继承。 final有最终的意思,不能继续进化了。
3、private方法。
instanceof:判断两个类是否有父子关系(返回true/false) sout ( X instanceod Y);
【若在object-person-student这个域里,则为true,否则为false,
若判断的两个类型父子关系(比如是姊妹关系),则报错】
类型转换:低(子)->高(父)可以自动转换,但可能会丢失自身的一些方法;
父->子需要强制转换:Person a = new Student();
Student b = (Student) a; b.go(); ==>简化成:((Student)a).go();
多态的作用:方便方法的调用,减少重复的代码。(子类父类可以调用互相的方法)
静态变量(static)推荐使用类名调用:Student.age而不是s1.age,这样就能知道这是一个静态变量。(静态变量才能通过类名调用,非静态调用只能通过对象s1调用)
同样,非静态方法只能通过new 类名().方法名();来调用;静态方法可以直接 类名().方法名();
非静态方法可以访问静态方法,静态方法不能调用非静态方法。
static还可以用来静态导入包
新建一个对象:1.最先执行静态代码块:static{……},一个类只执行一次
2.执行匿名代码块{……},与对象同时产生,用来赋初值。
3.执行构造方法 public Person(){……}
抽象类/抽象方法:
只有方法名字,没有方法的实现:public abstract class Action{
public abstract void doSomething(); }
抽象类的所有方法,继承了它的子类都必须要实现它的方法,除非子类也是抽象的(那就子子类去实现)。
public class A extends Action{
@Override
public void doSomething{ }
abstract有一个缺陷就是只能实现单继承,而接口便可以实现多继承了。
单继承也就是一个子类只有一个父类
多继承就是一个子类可以有多个父类
抽象类的作用:可提高开发效率,可以让别人来实现它的方法。(当多个类中出现相同功能,但是功能主体不同,这时可以进行向上抽取。这时,只抽取功能定义,而不抽取功能主体。)
抽象类的特点:1、不能new这个抽象类,只能靠子类去实现它。
2、抽象类中可以写普通的方法。
3、抽象方法必须在抽象类中。
【抽象类存在构造器,new子类自动执行父类构造】
接口:
本质是契约,像法律一样,制定好后大家都遵守。
(1)普通类:只有实现。
(2)抽象类:实现+规范(抽象方法)
(3)接口:只有规范(约束) 利用接口实现多继承
class ----> interface
接口中所有的定义都是抽象的:
public interface UserService { public abstract void add(String name);//public abstract是默认的,接口中所有定义的方法都是抽象的,可写可不写。 }
public interface TimeService { void timer(); }
注意:接口都需要有实现类---->以Impl结尾 : public class UserServiceImpl implements UserService,TimeService{ //实现了接口的类,就需要重写接口中的方法,不重写就会报错 @Override public void add(String name) { } @Override public void timer() { } }
*在接口里定义的属性默认都是常量(public static final)
接口不能被实例化(new),接口中没有构造方法。*
内部类:
成员内部类:
public class Outer {
private int id=10;//私有属性
public void out(){
System.out.println("外部类方法");
}
public class Inner{
public void in(){
System.out.println("内部类方法");
}
public void getID(){
System.out.println(id);//可以获得外部类私有属性!
}
}
}
静态内部类:即在Inner类public加上static,一旦加上static后, System.out.println(id)就会报错,除非把 private int id=10;换成 private static int id=10;(静态方法不能访问非静态属性)
局部内部类:
public class Outer2 { public void method(){ class Inner{ public void in(){ System.out.println("局部内部类"); } } } }
匿名内部类:
public class Outer3 {
public static void main(String[] args) {
new Apple().eat();//没有名字初始化类,不用将实例保存到变量中,节约内存
UserService userService=new UserService() {//实现接口的类,没有名字
@Override
public void hello() {
}
};
}
}
class Apple{
public void eat(){
System.out.println("eat");
}
}
interface UserService{
void hello();
}
异常:
Error:致命错误,JVM(Java虚拟机)终止线程。
Exception:可被程序处理。
RuntimeException:运行时异常(除了运行时异常其他的几种异常都是可以避免的)
ArrayIndexOutOfBoundsException:数组下标越界
NullPointerException:空指针异常
ArithmetricException:算术异常
MissingResourceException:丢失资源
ClassNotFoundException:找不到类
捕获异常:
public class Test1 { public static void main(String[] args) { int a = 1; int b = 0; try {//try监控区域 System.out.println(a / b); }catch (Exception e){//catch捕获异常 System.out.println("出现异常,b不能为0"); }finally {//finally处理善后工作,有无异常都执行,可省略,但如果有IO流等资源需关闭的情况就不可省。 System.out.println("finaly"); } } }
catch(想要捕获的异常类型 变量):类型最高是Throwable
Exception:捕获最大的异常
可以有好几个catch,捕获多个异常,其中Throwable放在最后(按从小到大的顺序依次排序:Error<Exception<Throwable
抛出异常:
选中System.out.println(a/b);然后ctrl+Alt+T,自动生成try-catch-finally
public class Test2 {
public static void main(String[] args) {
/*int a = 1;
int b = 0;
try {
System.out.println(a / b);
} catch (Exception e) {
System.exit(0);//最好选择手动结束
e.printStackTrace();
} finally {
}*/
try {
new Test2().test(1, 0);
} catch (ArithmeticException e) {
e.printStackTrace();
} finally {
}
//总结:throw、throws是运行时抛出异常,try-catch是遇到错误也能运行(让程序继续往下走)
}
public void test(int a,int b) throws ArithmeticException{//假设在这方法中,处理不了这个异常,则在方法上抛出异常 throws
if(b==0){
throw new ArithmeticException();//主动在方法内抛出是throw
}
System.out.println(a/b);
}
}
自定义异常:
//自定义异常
public class MyException extends Exception{
private int detail;
public MyException(int a) {//便于抛出MyException(a)
this.detail = a;
}
public MyException() {//显示定义无参构造
}
//Alt+insert-->toString方法:异常的打印信息
@Override
public String toString() {
return "MyException{" +
"detail=" + detail +
'}';
}
}
//测试 public class TestMyException { //可能会存在异常的方法 static void test(int b) throws MyException{ System.out.println("传递的参数为:"+b); if(b>10){ throw new MyException(b);//通过throws抛到外面去try-catch,也可以在方法里try-catch } System.out.println("Ok"); } public static void main(String[] args) { try {//自动捕获 test(19);//1是测试的数据 } catch (MyException e) { System.out.println("MyException=>"+e);//增加处理异常的代码 } }