回顾方法的定义
-
修饰符
-
返回类型
-
break和 return的区別
break:用来结束循环。 return:方法结束,返回一个结果。
-
方法名:注意命名规范 , 见名知意。
-
参数列表
-
异常抛出
回顾方法的调用
- 静态方法
- 非静态方法:需要构造实例化对象,进行调用。
- 形参和实参
- 值传递和引用传递
- 值传递:在方法被调用时,实参通过形参把它的内容副本传入方法内部,此时形参接收到的内容是实参值的一个拷贝,因此在方法内对形参的任何操作,都仅仅是对这个副本的操作,不影响原始值的内容。
- 引用传递:”引用”也就是指向真实内容的地址值,在方法调用时,实参的地址通过方法调用被传递给相应的形参,在方法体内,形参和实参指向同一块内存地址,对形参的操作会影响的真实内容。
- this关键字
- this指向自己的引用,即当前方法所在的对象。它的一个主要作用是要将自己这个对象当作参数,传送给别的对象中的方法。
类与对象的创建
类是一种抽象的数据类型,它是对某一类事物整体描述/定义,但是并不能代表某一个具体的事物。
对象是抽象概念的具体实例。
语法:
[类的修饰符] class 类名称 [extends 父类名称][implements 接口名称列表]
{
变量定义及初始化;
方法定义及方法体;
}
什么是面向对象
-
面向对象编程( Object- Oriented Programming,OOP)
-
面向对象编程的本质: 以类的方式组织代码,以对象的组织(装)数据。
-
抽象
-
三大特性
- 封装
- 继承
- 多态
-
从认识论角度考虑是先有对象后有类。对象,是具体的事物。类,是抽象的,是对对象的抽象。
-
从代码运行角度考虑是先有类后有对象。类是对象的模板。
创建与初始化对象
-
使用new关键字创建对象。
-
使用new关键字创建的时候,除了分配内存空间之外,还会给创建好的对象进行默认的初始化以及对类中构造器的调用。
-
类中的构造器也称为构造方法,是在进行创建对象的时候必须要调用的。并且构造器有以下俩个特点:
- 必须和类的名字相同。
- 必须没有返回类型,也不能写void。
-
构造器必须要掌握。
例子:
public class Person {
private String name;
private int age;
//无参构造器
public Person() {
}
//有参构造器:一旦定义了有参构造,无参就必须显示定义
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
public static void main(String[] args) {
Person[] people = new Person[4];
people[0] = new Person("yt", 20);
people[1] = new Person("wx", 21);
people[2] = new Person("wx", 20);
people[3] = new Person("wx", 23);
Person persons = new Person();
System.out.println(Arrays.toString(people));
}
}
创建对象的内存分析
对象是通过引用操作的: 栈—>堆
例子:
public class Pet {
String name;
int age;
public void shout(){
System.out.println("叫了一声");
}
}
public class Application {
public static void main(String[] args) {
Pet dog = new Pet();
dog.name = "旺财";
dog.age = 3;
dog.shout();
System.out.println(dog.name);
System.out.println(dog.age);
Pet cat = new Pet();
}
}
封装
该露的露,该藏的藏
- 我们程序设计要追求 “高内聚,低耦合” 。高内緊就是类的内部数据操作细节自己完成,不允许外部干涉;低耦合:仅暴露少量的方法给外部使用。
封装(数据的隐藏)
- 通常,应禁止直接访问一个对象中数据的实际表示,而应通过操作接口来访问,这称为信息隐藏。
记住这句话就够了: 属性私有,get/set
例子:
public class Person {
private String name;
private int age;
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
继承
继承的本质是对某一批类的抽象,从而实现对现实世界更好的建模。
extands的意思是“”扩展”。子类是父类的扩展。
Java中类只有单继承,没有多继承!(接口可以多继承)
继承是类和类之间的一种关系。除此之外,类和类之间的关系还有依赖、组合、聚合等。
继承关系的俩个类,一个为子类(派生类),一个为父类(基类)。子类继承父类,使用关键字 extends来表示。
子类和父类之间,从意义上讲应该具有”isa”的关系。
final修饰的类无法继承。
例子:
public class Person {
private String name;
private int age;
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
}
public class Student extends Person {
public Student(){
//隐藏代码:调用父类的无参构造 super();
//调用父类的构造器,必须要在子类构造器的第一行
//如果父类没有无参构造器,子类无法调用父类的无参构造器,但是可以调用父类的有参构造器,实现无参构造器
}
}
public class Teacher extends Person{
}
子类继承了父类,就会拥有父类的全部方法。
稀有的属性和方法无法被继承。
object类
- 在Java中,所有的类都默认直接或间接继承Object类。
super
- super调用父类的构造方法,必须在构造方法的第一行。
- super必须只能出现在子类的方法或者构造方法中。
- super和this不能同时调用构造方法。
方法重写
- 重写都是方法的重写,和属性无关。
- 子类重写父类的方法
- 方法名必须相同。
- 参数列表必须相同。
- 修饰符:范围可以扩大,不可以缩小, public>protected>default>private。
- 抛出异常范围:可以缩小,不可以扩大。
- 静态方法:方法的调用只和左边,定义的数据类型有关。
- 非静态方法:重写。
- 为什么要重写?
- 父类功能,子类不一定需要,或者不一定满足。
例子:
public class B {
public void test(){
System.out.println("B=>test");
}
}
public class A extends B{
@Override
public void test(){
System.out.println("A=>test");
}
}
public class Application {
public static void main(String[] args) {
A a=new A();
a.test();
//父类的引用指向了子类
B b=new A();//子类重写了父类的方法
b.test();
}
}
A=>test
A=>test
多态
即同一方法可以根据发送对象的不同而采用多种不同的行为方式。
一个对象的实际类型是确定的,但可以指向对象的引用的类型有很多。
动态编译: 类型可扩展。
多态存在的条件
- 有继承关系
- 子类重写父类方法
- 父类引用指向子类对象
例子:
public class Student extends Person {
}
public class Application {
public static void main(String[] args) {
//一个对象的实际类型是确定的
//new Student();
//new Person();
//可以指向的引用类型就不确定了:父类的引用指向子类
//Student 能调用的方法都是自己的或者继承父类的
Student s1 = new Student();
//Person 父类型,可以指向子类,但是不能调用子类独有的方法
Person s2 = new Student();
Object s3 = new Student();
//对象能执行那些方法,主要看对象左边的数据类型,和右边的new关系不大
}
}
注意:
- 多态是方法的多态,属性没有多态性。
- 父类和子类,有联系,类型转换异常!ClassCastException!
instanceof (类型转换) 引用类型
例子:
public class Application {
public static void main(String[] args) {
//Object string
//Object Person Teacher
//Object Person Student
Object object = new Student();
System.out.println(object instanceof Student); //true
System.out.println(object instanceof Person);//true
System.out.println(object instanceof Object); //true
System.out.println(object instanceof Teacher); //false
System.out.println(object instanceof String); //false
Person person = new Student();
System.out.println(person instanceof Student); //true
System.out.println(person instanceof Person); //true
System.out.println(person instanceof Object); //true
System.out.println(person instanceof Teacher); //false
//System.out.println(person instanceof String);//编译错误
}
}
类型之间的转换: 父 —–> 子
高—>低 强制转换
低—>高 自动转换
子类转父类 会损失自己本来的一些方法。
方便方法的调用,减少重复的代码!
static关键字
static修饰属性,需要通过类名去调用。
静态变量多用于多线程。
静态方法无法之间调用非静态方法,需要通过实例化对象进行调用,可以直接调用当前类的静态方法,或者通过类名调用其他类的静态方法。
非静态方法可以直接调用当前类的静态方法。
{
//匿名代码块,创建对象的时候执行,在构造器前面
}
static{
//静态代码块,类加载的时候,永久执行一次
}
静态导入包
import static java.lang.Math.PI;
import static java.lang.Math.random;
public class Application {
public static void main(String[] args) {
System.out.println(random());
System.out.println(PI);
}
}
抽象类
abstract修饰符可以用来修饰方法也可以修饰类,如果修饰方法,那么该方法就是抽象方法;如果修饰类,那么该类就是抽象类。
抽象类中可以没有抽象方法,但是有抽象方法的类一定要声明为抽象类。
抽象类,不能使用new关键字来创建对象,它是用来让子类继承的。
抽象方法,只有方法的声明没有方法的实现,它是用来让子类实现的。
子类继承抽象类,那么就必须要实现抽象类没有实现的抽象方法,否则该子类也要声明为抽象类。
例子:
public abstract class B {
public void test(){
}
}
public class A extends B{
@Override
public void test(){
System.out.println("A=>test");
}
}
接口
普通类: 只有具体实现
抽象类: 具体实现和规范(抽象方法)都有!
接口: 只有规范!自己无法写方法!约束和实现分离:面向接口编程
OO的精髓,是对对象的抽象,最能体现这一点的就是接口。 为什么我们讨论设计模式都只针对具备了抽象能力的语言(比如c++、java、c#等),就是因为设计模式所研究的,实际上就是如何合理的去抽象
声明类的关键字是 class,声明接口的关键字是 interface。
例子:
public interface UserServiceDao {
/** * @param user * 登录 * @return boolean */
public boolean login(User user);
/** * @param user * 注册 * @return boolean */
public boolean register(User user);
/** * @param user * 更新 * @return */
public void update(User user);
}
方法修饰 public abstract
属性修饰 public static final
接口不能实例化,没有构造方法。
implements可以实现多个接口。
内部类
内部类就是在一个类的内部在定义一个类,比如,A类中定义一个B类,那么B类相对A类来说就称为内部类,而A类相对B类来说就是外部类了。
- 成员内部类
- 静态内部类
- 局部內部类
- 匿名内部类
- Lambda表达式
成员内部类
例子:
public class Outer {
private int id=10;
public void out(){
System.out.println("这是外部类方法");
}
class Inner{
public void in(){
System.out.println("这是内部类方法");
}
//获得外部类的私有属性
public void getID(){
System.out.println(id);
}
}
}
public class Application {
public static void main(String[] args) {
Outer outer = new Outer();
//通过外部类来实现内部类
Outer.Inner inner = outer.new Inner();
inner.in();
inner.getID();
}
}
静态内部类
例子:
public class Outer {
private int id=10;
public void out(){
System.out.println("这是外部类方法");
}
static class Inner{
public void in(){
System.out.println("这是内部类方法");
}
}
}
局部内部类
例子:
public class Outer {
private int id=10;
public void out(){
System.out.println("这是外部类方法");
}
public void method(){
class Inner{
public void in(){
System.out.println("这是内部类方法");
}
}
}
}
匿名内部类
例子:
public class Application {
public static void main(String[] args) {
//没有名字初始化类,不用将实例保存到变量中
new Apple().eat();
}
}
class Apple{
public void eat(){
System.out.println("1");
}
}
Lambda表达式
Lambda表达式(也称为闭包),Lambda允许把函数作为一个方法的参数(函数作为参数传递进方法中),或者把代码看成数据。一个Lambda可以由用逗号分隔的参数列表、–>符号与函数体三部分表示。
使用 Lambda 表达式可以使代码变的更加简洁紧凑。
语法:
(parameters) -> expression
或
(parameters) ->{
statements; }
以下是lambda表达式的重要特征:
- 可选类型声明: 不需要声明参数类型,编译器可以统一识别参数值。
- 可选的参数圆括号: 一个参数无需定义圆括号,但多个参数需要定义圆括号。
- 可选的大括号: 如果主体包含了一个语句,就不需要使用大括号。
- 可选的返回关键字: 如果主体只有一个表达式返回值则编译器会自动返回值,大括号需要指定明表达式返回了一个数值。
Lambda 表达式实例
// 1. 不需要参数,返回值为 5
() -> 5
// 2. 接收一个参数(数字类型),返回其2倍的值
x -> 2 * x
// 3. 接受2个参数(数字),并返回他们的差值
(x, y) -> x – y
// 4. 接收2个int型整数,返回他们的和
(int x, int y) -> x + y
// 5. 接受一个 string 对象,并在控制台打印,不返回任何值(看起来像是返回void)
(String s) -> System.out.print(s)
例子:
public class Java8Tester {
public static void main(String args[]){
Java8Tester tester = new Java8Tester();
// 类型声明
MathOperation addition = (int a, int b) -> a + b;
// 不用类型声明
MathOperation subtraction = (a, b) -> a - b;
// 大括号中的返回语句
MathOperation multiplication = (int a, int b) -> {
return a * b; };
// 没有大括号及返回语句
MathOperation division = (int a, int b) -> a / b;
System.out.println("10 + 5 = " + tester.operate(10, 5, addition));
System.out.println("10 - 5 = " + tester.operate(10, 5, subtraction));
System.out.println("10 x 5 = " + tester.operate(10, 5, multiplication));
System.out.println("10 / 5 = " + tester.operate(10, 5, division));
// 不用括号
GreetingService greetService1 = message ->
System.out.println("Hello " + message);
// 用括号
GreetingService greetService2 = (message) ->
System.out.println("Hello " + message);
greetService1.sayMessage("Runoob");
greetService2.sayMessage("Google");
}
interface MathOperation {
int operation(int a, int b);
}
interface GreetingService {
void sayMessage(String message);
}
private int operate(int a, int b, MathOperation mathOperation){
return mathOperation.operation(a, b);
}
}
输出结果为:
10 + 5 = 15
10 - 5 = 5
10 x 5 = 50
10 / 5 = 2
Hello Runoob
Hello Google
使用 Lambda 表达式需要注意以下两点:
- Lambda 表达式主要用来定义行内执行的方法类型接口,例如,一个简单方法接口。在上面例子中,我们使用各种类型的Lambda表达式来定义MathOperation接口的方法。然后我们定义了sayMessage的执行。
- Lambda 表达式免去了使用匿名方法的麻烦,并且给予Java简单但是强大的函数化的编程能力。
变量作用域
lambda 表达式只能引用标记了 final 的外层局部变量,这就是说不能在 lambda 内部修改定义在域外的局部变量,否则会编译错误。
例子:
public class Java8Tester {
final static String salutation = "Hello! ";
public static void main(String args[]){
GreetingService greetService1 = message ->
System.out.println(salutation + message);
greetService1.sayMessage("Runoob");
}
interface GreetingService {
void sayMessage(String message);
}
}
输出结果为:
Hello! Runoob
我们也可以直接在 lambda 表达式中访问外层的局部变量:
例子:
public class Java8Tester {
public static void main(String args[]) {
final int num = 1;
Converter<Integer, String> s = (param) -> System.out.println(String.valueOf(param + num));
s.convert(2); // 输出结果为 3
}
public interface Converter<T1, T2> {
void convert(int i);
}
}
lambda 表达式的局部变量可以不用声明为 final,但是必须不可被后面的代码修改(即隐性的具有 final 的语义)
int num = 1;
Converter<Integer, String> s = (param) -> System.out.println(String.valueOf(param + num));
s.convert(2);
num = 5;
//报错信息:Local variable num defined in an enclosing scope must be final or effectively
final
在 Lambda 表达式当中不允许声明一个与局部变量同名的参数或者局部变量。
String first = "";
Comparator<String> comparator = (first, second) -> Integer.compare(first.length(), second.length()); //编译会出错
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/114432.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...