Estou totalmente confuso agora - principalmente por causa da terminologia, eu acho. Alguém pode me explicar as diferenças ou fornecer alguns links para materiais à prova de fictícios? Especialmente URI para URL e Recurso para Arquivo? Para mim, parece que deveriam ser a mesma coisa, respectivamente ...
A terminologia é confusa e às vezes atordoante, e principalmente nasceu da evolução do Java como uma API e como uma plataforma ao longo do tempo. Para entender como esses termos passaram a significar o que significam, é importante reconhecer duas coisas que influenciam o design do Java:
- Compatibilidade com versões anteriores. Os aplicativos antigos devem ser executados em instalações mais recentes, de preferência sem modificações. Isso significa que uma API antiga (com seus nomes e terminologia) precisa ser mantida em todas as versões mais recentes.
- Plataforma cruzada. A API deve fornecer uma abstração utilizável de sua plataforma subjacente, seja um sistema operacional ou um navegador.
Vou examinar os conceitos e como eles surgiram. Vou responder suas outras perguntas específicas depois disso, porque posso ter que me referir a algo na primeira parte.
O que é um "Recurso"?
Um dado genérico e abstrato que pode ser localizado e lido. Em poucas palavras, Java usa isso para se referir a um "arquivo" que pode não ser um arquivo, mas representa uma parte nomeada de dados. Ele não tem uma classe direta ou representação de interface em Java , mas por causa de suas propriedades (localizável, legível), geralmente é representado por uma URL.
Como um dos primeiros objetivos de design do Java era ser executado dentro de um navegador, como um aplicativo em sandbox (applets!) Com direitos / privilégios / autorização de segurança muito limitados, o Java faz uma diferença (teórica) clara entre um arquivo (algo no local sistema de arquivos) e um recurso (algo que ele precisa ler). É por isso que a leitura de algo relativo ao aplicativo (ícones, arquivos de classe e assim por diante) é feita por meio ClassLoader.getResource
e não por meio da classe File.
Infelizmente, como "recurso" também é um termo genérico útil fora dessa interpretação, ele também é usado para nomear coisas muito específicas (por exemplo, classe ResourceBundle , UIResource , Resource ) que não são, neste sentido, um recurso.
As principais classes que representam (um caminho para) um recurso são java.nio.file.Path , java.io.File , java.net.URI e java.net.URL .
Arquivo (java.io, 1.0)
Uma representação abstrata de nomes de caminho de arquivo e diretório.
A classe File representa um recurso que pode ser acessado por meio do sistema de arquivos nativo da plataforma . Ele contém apenas o nome do arquivo, então é realmente mais um caminho (veja mais tarde) que a plataforma host interpreta de acordo com suas próprias configurações, regras e sintaxe.
Observe que Arquivo não precisa apontar para algo local , apenas algo que a plataforma host entenda no contexto de acesso ao arquivo, por exemplo, um caminho UNC no Windows. Se você montar um arquivo ZIP como um sistema de arquivos em seu sistema operacional, o Arquivo lerá suas entradas contidas perfeitamente.
URL (java.net, 1.0)
URL de classe representa um Localizador Uniforme de Recursos, um ponteiro para um "recurso" na World Wide Web. Um recurso pode ser algo tão simples como um arquivo ou diretório, ou pode ser uma referência a um objeto mais complicado, como uma consulta a um banco de dados ou a um mecanismo de pesquisa.
Paralelamente ao conceito de recurso, a URL representa esse recurso da mesma forma que a classe File representa um arquivo na plataforma host: como uma string estruturada que aponta para um recurso. A URL contém adicionalmente um esquema que sugere como acessar o recurso (com "arquivo:" sendo "pergunte à plataforma do host") e, portanto, permite apontar para recursos por meio de HTTP, FTP, dentro de um JAR e outros enfeites.
Infelizmente, os URLs vêm com sua própria sintaxe e terminologia, incluindo o uso de "arquivo" e "caminho". Caso a URL seja uma URL de arquivo, URL.getFile retornará uma string idêntica à string do caminho do arquivo referenciado.
Class.getResource
retorna um URL: é mais flexível do que retornar File e atendeu às necessidades do sistema imaginadas no início dos anos 90.
URI (java.net, 1.4)
Representa uma referência de URI (Uniform Resource Identifier).
URI é uma (leve) abstração sobre URL. A diferença entre URI e URL é conceitual e principalmente acadêmica, mas URI é melhor definido em um sentido formal e cobre uma gama mais ampla de casos de uso. Como URL e URI são / não são a mesma coisa, uma nova classe foi introduzida para representá-los, com os métodos URI.toURL e URL.toURI para mover entre um e outro.
Em Java, a principal diferença entre URL e URI é que uma URL carrega a expectativa de ser resolvida , algo a partir do qual o aplicativo pode querer um InputStream; um URI é tratado mais como um thingamajig abstrato que pode apontar para algo resolvível (e geralmente faz), mas o que significa e como alcançá-lo são mais abertos ao contexto e interpretação.
Caminho (java.nio.file, 1.7)
Um objeto que pode ser usado para localizar um arquivo em um sistema de arquivos. Normalmente representa um caminho de arquivo dependente do sistema.
A nova API de arquivo, iconificada na interface Path, permite uma flexibilidade muito maior do que a classe File poderia oferecer. A interface Path é uma abstração da classe File e faz parte da New IO File API . Onde File necessariamente aponta para um "arquivo" conforme entendido pela plataforma host, Path é mais genérico: ele representa um arquivo (recurso) em um sistema de arquivos arbitrário .
O caminho tira a confiança no conceito de arquivo da plataforma host. Pode ser uma entrada em um arquivo ZIP, um arquivo acessível por FTP ou SSH-FS, uma representação com várias raízes do classpath do aplicativo ou realmente qualquer coisa que possa ser representada de forma significativa por meio da interface FileSystem e seu driver, FileSystemProvider. Ele traz o poder de "montar" sistemas de arquivos no contexto de um aplicativo Java.
A plataforma host é representada por meio do "sistema de arquivos padrão"; quando você chama File.toPath
, você obtém um caminho no sistema de arquivos padrão.
Agora, se eu tiver um localizador que faz referência a uma classe ou pacote em um arquivo jar, esses dois (isto é, caminho e strings de arquivo) serão diferentes?
Improvável. Se o arquivo jar é no sistema de arquivos local, você não deve ter um componente de consulta, de modo URL.getPath
e URL.getFile
deve retornar o mesmo resultado. No entanto, escolha o que você precisa: arquivos-URLs podem não ter componentes de consulta, mas eu poderia adicionar um de qualquer maneira.
Por último - e mais importante - por que preciso do objeto File; por que um Recurso (URL) não é suficiente?
URL pode não ser suficiente porque Arquivo fornece acesso a dados de manutenção, como permissões (legível, gravável, executável), tipo de arquivo (sou um diretório?) E a capacidade de pesquisar e manipular o sistema de arquivos local. Se esses forem os recursos de que você precisa, Arquivo ou Caminho os fornecerá.
Você não precisa do Arquivo se tiver acesso ao Caminho. No entanto, algumas APIs mais antigas podem exigir o arquivo.
(E existe um objeto Resource?)
Não, não há. Há muitas coisas com nomes semelhantes, mas não são um recurso no sentido de ClassLoader.getResource
.
Path
e FileSystem de NIO :)