声明:本博客为本人的个人学习笔记,内容均由网上资源整理而来,若有内容错误,欢迎指正,若有侵权,立即删除。
待补充
正式回答:
下面开始说人话:
多态就是在定义时不明确引用指向那个具体的类型(一般指向父类),在运行时才明确具体指向(具体指向哪个子类)。
举个例子:
歌曲类,有两个子类,中文歌,英文歌
父类:歌曲类:
public class Song {public void printText() {System.out.println("唱歌");}
}
子类1:中文歌
public class ChineseSong extends Song {@Overridepublic void printText() {System.out.println("唱中文歌");}
}
子类2:英文歌
public class EnglishSong extends Song {@Overridepublic void printText() {System.out.println("唱英文歌");}
}
persion类有个方法唱歌[Sing()]
示范一:没有使用多态
当前业务要求需要人类唱中文歌,则需这样定义persion类
public class Persion {public void sing(ChineseSong cheineseSong ) {cheineseSong.printText();}
}
若干天后业务变化,需要人类唱英文歌,则需将persion类改为
public class Persion {public void sing(EnglishSong englishSong ) {englishSong .printText();}
}
此时,随着业务变化,程序员需要不停的改动persion类来适配当前业务。
示范二:使用了多态
public class Persion {public void sing(Song song) {song.printText();}
}
在定义sing() 方法时,将歌曲类的父类传入,并没有指定是哪个具体的子类。在业务发生变化时,只需在调用时再传入具体的Song子类即可,若有新的需求,例如唱韩文歌,只需创建新的类,继承Song,然后即可传入即可,在这期间并不需要对Persion类做修改,实现解耦。
举个例子:有2个类,Father 是父类,Son 类继承自 Father。
Father f1 = new Son(); // 这就叫 upcasting (向上转型)
Son s1 = (Son)f1; // 这就叫 downcasting (向下转型)注意:直接使用子类对象的引用指向父类对象,是错的,并不是向下转型
Father f2 = new Father();
Son s2 = (Son)f2; // 出错,子类引用不能直接指向父类对象
使用向上转型时,会丢失子类中独有的方法。例如:
父类:
public class Animal {public void eat(){System.out.println("");}
}子类:
class Bird extends Animal{public void eat(){System.out.println("");}public void fly(){System.out.println("");}}测试类:class Main{public static void doEat(Animal h) {h.eat();}public static void main(String[] args) {Animal b=new Bird(); //向上转型b.eat(); //! error: b.fly(); b虽指向子类对象,但此时丢失fly()方法//可通过向下转型的方式再次获取Bird b2 = (Bird)b;b2.fly();Animail c1=new Animal();Bird c2=new Bird();doEat(c1);doEat(c2);//此处参数存在向上转型}}
1、字节流在操作的时候本身是不会用到缓冲区(内存)的,是与文件本身直接操作的,而字符流在操作的时候是使用到缓冲区的
2、字节流在操作文件时,即使不关闭资源(close方法),文件也能输出,但是如果字符流不使用close方法的话,则不会输出任何内容,说明字符流用的是缓冲区,并且可以使用flush方法强制进行刷新缓冲区,这时才能在不close的情况下输出内容
3、Reader类的read()方法返回类型为int :作为整数读取的字符(占两个字节共16位),范围在 0 到 65535 之间 (0x00-0xffff),如果已到达流的末尾,则返回 -1
inputStream的read()虽然也返回int,但由于此类是面向字节流的,一个字节占8个位,所以返回 0 到 255 范围内的 int 字节值。如果因为已经到达流末尾而没有可用的字节,则返回值 -1。因此对于不能用0-255来表示的值就得用字符流来读取!比如说汉字.
4、字节流与字符流主要的区别是他们的的处理方式
字节流:处理字节和字节数组或二进制对象;
字符流:处理字符、字符数组或字符串。
User类定义
public class User {}
xml文件中配置bean
<bean id="user" class="com.User"/>
对User的使用
public class Test {public static void main(String[] args) {//这里还可以直接使用顶级接口BeanFactoryApplicationContext context = new FileSystemXmlApplicationContext("l");//按类型获取by typeUser user1 = Bean(User.class);//按名称获取by name(在配置文件中,我们将bean声明为了user)User user2 = (User) Bean("user");}
}
1.2 依赖注入
1.2.1 接口注入:
1.2.2 Setter注入:基于JavaBean的set()方法为属性赋值。在实际开发中得到了最广泛的应用。
配置文件
<bean id="user" class="com.User"><property name="name" value="张三"/><property name="age" value="20"/>
</bean>
测试类
public class Test {public static void main(String[] args) {//这里还可以直接使用顶级接口BeanFactoryApplicationContext context = new FileSystemXmlApplicationContext("l");//按类型获取by typeMybatis user= Bean(User.class);System.out.Name());System.out.Age());}
}
1.2.3 构造器注入:基于构造方法为属性赋值,容器通过调用类的构造方法,将其所需的依赖关系注入其中。
配置文件
注意:这里要和构造方法的参数顺序一致,否则会产生异常
<bean id="user" class="com.User"><constructor-arg value="张三"/><constructor-arg value="李四"/>
</bean>
测试类 和上面的Setter测试没有区别
public class Test {public static void main(String[] args) {//这里还可以直接使用顶级接口BeanFactoryApplicationContext context = new FileSystemXmlApplicationContext("l");//按类型获取by typeMybatis user= Bean(User.class);System.out.Name());System.out.Age());}
}
2 通过注解实现
实体类定义
public class User {private String name;private String age;//省略set/get和构造方法
}
@Configuration注解的配置文件,作用相当于xml配置文件
@Configuration
public class AppConfig {@Bean(name="user")public User initUser() {User user = new User();user.setName("zepal");user.setAge("18");return user;}
}
测试类
public class Test {ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);User user = (User) Bean("user");}
ps:
通过扫描装配Bean,一般使用@Component+@ComponentScan组合。
@Component用于标记哪个类被扫描进IoC,@ComponentScan则是标明采用哪种策略去扫描装配Bean。类似于XML中的context:component-scan标签。
@Component可以指定Bean的名称,如果不指定,则按照类型首字母小写作为Bean的名称,byName获取的时候注意。@ComponentScan默认扫描当前包或其子包,所以一般在springboot项目中,所有包都是启动包的子包,@SpringBootApplication启动注解,在1.5之后包含了@ComponentScan注解,所以在SpringBoot中不单独指定。所以像我们的服务层用的@Service注解才会被扫描注册为Bean,@Service里也涵盖了@Component注解。
@ComponentScan在指定扫面包的时候可以采用通配符,还有一些其他功能比如过滤器,指定不扫描哪些包等等。
例如:
支付接口
interface Pay() {private void pay();
}
具体支付实现类:支付宝
Class AliPay() {@Overrideprivate void pay(){sout("调用支付宝");}
}
具体支付实现类:微星
Class WeChatPay() {@Overrideprivate void pay(){sout("调用微信");}
}
业务中具体的支付调用方法
type为客户端传过来的支付方式,例如为:"com.AliPay"或是"com.WeChatPay"(为AliPay或WeChatPay的类全名)。
public void realPay(String type) {Class cls= Class.forName(type);//依据类全名获取classObject o = wInstance();//新建类Method mothod = Method("pay");//获取类方法mehtod.invoke(o);//调用类方法
}
具体的支付调用方法中,并没有写死调用哪个类的方法,而是在动态过程中依据参数,动态的创建类,调用对应的方法。在业务变化时提高了代码的复用性。
注解 | 作用位置 | 作用 |
---|---|---|
@RequestBody | 方法上 | 主要用来接收前端传递给后端的json字符串中的数据的(请求体中的数据的),GET方式无请求体,所以使用@RequestBody接收数据时,前端不能使用GET方式提交数据,而是用POST方式进行提交。在后端的同一个接收方法里,@RequestBody与@RequestParam()可以同时使用,@RequestBody最多只能有一个,而@RequestParam()可以有多个。 |
@ResponseBody | 方法上 | 将controller的方法返回的对象通过适当的转换器转换为指定的格式之后,写入到response对象的body区,通常用来返回JSON数据或者是XML数据。 |
@Controller | 类上 | 此注解使用在class上声明此类是一个Spring controller。 |
@RestController | 类上 | 相当于@Controller+@ResponseBody两个注解的结合,返回json数据不需要在方法前面加@ResponseBody注解了,但使用@RestController这个注解,就不能返回jsp,html页面,视图解析器无法解析jsp,html页面 |
@RequestParam | 方法参数之前 | 该注解的作用是把请求中指定名称的参数给控制器中的形参赋值。其中该注解有两个属性:value:请求参数中的名称。required:请求参数中是否必须提供此参数。默认值:true。表示必须提供,如果不提供将报错。 |
@PathVariable(“xxx“) | 方法上 | 通过 @PathVariable 可以将URL中占位符参数{xxx}绑定到处理器类的方法形参中@PathVariable(“xxx“) |
@RequestMapping | 类上或是方法上 | 是一个用来处理请求地址映射的注解,可用于类或方法上。用于类上,表示类中的所有响应请求的方法都是以该地址作为父路径。 |
博客园:JAVA设计模式总结之23种设计模式
参考引用文档:
百度知道:java里,方法重载是不是多态的一种实现?
CSDN:字符流与字节流的区别
博客园:谈谈对springIoc的理解
CSDN:SpringMVC基础中常用注解及其作用
CSDN:@PathVariable注解使用
CSDN:@RequestBody的使用
博客园:为什么要用泛型呢
深入理解什么是Java泛型?泛型怎么使用?
博客园:Java 转型问题(向上转型和向下转型)
本文发布于:2024-02-03 07:06:53,感谢您对本站的认可!
本文链接:https://www.4u4v.net/it/170691521149430.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |